Print this page
make: unifdef for MAKETOOL and DISTRIBUTED (undefined)


  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      doname.c
  28  *
  29  *      Figure out which targets are out of date and rebuild them
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <alloca.h>               /* alloca() */
  36 
  37 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
  38 #       include <avo/strings.h>   /* AVO_STRDUP() */
  39 #       include <dm/Avo_MToolJobResultMsg.h>
  40 #       include <dm/Avo_MToolJobStartMsg.h>
  41 #       include <dm/Avo_MToolRsrcInfoMsg.h>
  42 #       include <dm/Avo_macro_defs.h> /* AVO_BLOCK_INTERUPTS & AVO_UNBLOCK_INTERUPTS */
  43 #       include <dmthread/Avo_ServerState.h>
  44 #       include <rw/pstream.h>
  45 #       include <rw/xdrstrea.h>
  46 #endif
  47 
  48 #include <fcntl.h>
  49 #include <mk/defs.h>
  50 #include <mksh/i18n.h>            /* get_char_semantics_value() */
  51 #include <mksh/macro.h>           /* getvar(), expand_value() */
  52 #include <mksh/misc.h>            /* getmem() */
  53 #include <poll.h>
  54 
  55 
  56 #include <signal.h>
  57 
  58 #       include <stropts.h>
  59 
  60 #include <sys/errno.h>
  61 #include <sys/stat.h>
  62 #include <sys/types.h>
  63 #include <sys/utsname.h>  /* uname() */
  64 #include <sys/wait.h>
  65 #include <unistd.h>               /* close() */
  66 
  67 /*
  68  * Defined macros
  69  */
  70 #       define LOCALHOST "localhost"
  71 
  72 #define MAXRULES 100
  73 
  74 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
  75 #define SEND_MTOOL_MSG(cmds) \
  76         if (send_mtool_msgs) { \
  77                 cmds \
  78         }
  79 #else
  80 #define SEND_MTOOL_MSG(cmds) 
  81 #endif
  82 
  83 // Sleep for .1 seconds between stat()'s
  84 const int       STAT_RETRY_SLEEP_TIME = 100000;
  85 
  86 /*
  87  * typedefs & structs
  88  */
  89 
  90 /*
  91  * Static variables
  92  */
  93 static char     hostName[MAXNAMELEN] = "";
  94 static char     userName[MAXNAMELEN] = "";
  95 
  96 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
  97         static FILE     *mtool_msgs_fp;
  98         static XDR      xdrs;
  99         static int      sent_rsrc_info_msg = 0;
 100 #endif
 101 
 102 static int      second_pass = 0;
 103 
 104 /*
 105  * File table of contents
 106  */
 107 extern  Doname          doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
 108 extern  Doname          doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
 109 static  Boolean         check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
 110 void            dynamic_dependencies(Name target);
 111 static  Doname          run_command(register Property line, Boolean print_machine);
 112 extern  Doname          execute_serial(Property line);
 113 extern  Name            vpath_translation(register Name cmd);
 114 extern  void            check_state(Name temp_file_name);
 115 static  void            read_dependency_file(register Name filename);
 116 static  void            check_read_state_file(void);
 117 static  void            do_assign(register Name line, register Name target);
 118 static  void            build_command_strings(Name target, register Property line);
 119 static  Doname          touch_command(register Property line, register Name target, Doname result);
 120 extern  void            update_target(Property line, Doname result);
 121 static  Doname          sccs_get(register Name target, register Property *command);
 122 extern  void            read_directory_of_file(register Name file);
 123 static  void            add_pattern_conditionals(register Name target);
 124 extern  void            set_locals(register Name target, register Property old_locals);
 125 extern  void            reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
 126 extern  Boolean         check_auto_dependencies(Name target, int auto_count, Name *automatics);
 127 static  void            delete_query_chain(Chain ch);
 128 
 129 // From read2.cc
 130 extern  Name            normalize_name(register wchar_t *name_string, register int length);
 131 
 132 
 133 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
 134         static void             append_job_result_msg(Avo_MToolJobResultMsg *job_result_msg);
 135         static int              pollResults(char *outFn, char *errFn, char *hostNm);
 136         static void             pollResultsAction(char *outFn, char *errFn);
 137         static void             rxmGetNextResultsBlock(int fd);
 138         static int              us_sleep(unsigned int nusecs);
 139         extern "C" void         Avo_PollResultsAction_Sigusr1Handler(int foo);
 140 #endif
 141 
 142 /*
 143  * DONE.
 144  *
 145  *      doname_check(target, do_get, implicit, automatic)
 146  *
 147  *      Will call doname() and then inspect the return value
 148  *
 149  *      Return value:
 150  *                              Indication if the build failed or not
 151  *
 152  *      Parameters:
 153  *              target          The target to build
 154  *              do_get          Passed thru to doname()
 155  *              implicit        Passed thru to doname()
 156  *              automatic       Are we building a hidden dependency?
 157  *
 158  *      Global variables used:
 159  *              build_failed_seen       Set if -k is on and error occurs
 160  *              continue_after_error    Indicates that -k is on


1002              dependency != NULL;
1003              dependency = dependency->next) {
1004                 Boolean this_dependency_changed = false;
1005 
1006                 if (!dependency->automatic &&
1007                     (rechecking_target || target->rechecking_target)) {
1008                         /*
1009                          * We only bother with the autos when rechecking
1010                          */
1011                         continue;
1012                 }
1013 
1014                 if (dependency->name == wait_name) {
1015                         /*
1016                          * The special target .WAIT means finish all of
1017                          * the prior dependencies before continuing.
1018                          */
1019                         if (dependencies_running) {
1020                                 break;
1021                         }
1022 #ifdef DISTRIBUTED
1023                 } else if ((!parallel_ok(dependency->name, false)) &&
1024                            (dependencies_running)) {
1025                         /*
1026                          * If we can't execute the current dependency in
1027                          * parallel, hold off the dependency processing
1028                          * to preserve the order of the dependencies.
1029                          */
1030                         break;
1031 #endif
1032                 } else {
1033                         timestruc_t     depe_time = file_doesnt_exist;
1034 
1035 
1036                         if (true_target->is_member) {
1037                                 depe_time = exists(dependency->name);
1038                         }
1039                         if (dependency->built ||
1040                             (dependency->name->state == build_failed)) {
1041                                 dep_result = (Doname) dependency->name->state;
1042                         } else {
1043                                 dep_result = doname_check(dependency->name,
1044                                                           do_get,
1045                                                           false,
1046                                                           (Boolean) dependency->automatic);
1047                         }
1048                         if (true_target->is_member || dependency->name->is_member) {
1049                                 /* should compare only secs, cause lib members does not have nsec time resolution */
1050                                 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
1051                                         this_dependency_changed =


1827  *      Return value:
1828  *                              The result of the command build
1829  *
1830  *      Parameters:     
1831  *              line            The command to execute
1832  *
1833  *      Static variables used:
1834  *
1835  *      Global variables used:
1836  *              continue_after_error -k flag
1837  *              do_not_exec_rule -n flag
1838  *              report_dependencies -P flag
1839  *              silent          Don't echo commands before executing
1840  *              temp_file_name  Temp file for auto dependencies
1841  *              vpath_defined   If true, translate path for command
1842  */
1843 Doname
1844 execute_serial(Property line)
1845 {
1846         int                     child_pid = 0;
1847 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
1848         Avo_MToolJobResultMsg   *job_result_msg;
1849         RWCollectable           *xdr_msg;
1850 #endif
1851         Boolean                 printed_serial;
1852         Doname                  result = build_ok;
1853         Cmd_line                rule, cmd_tail, command = NULL;
1854         char                    mbstring[MAXPATHLEN];
1855         int                     filed;
1856         Name                    target = line->body.line.target;
1857 
1858         SEND_MTOOL_MSG(
1859                 if (!sent_rsrc_info_msg) {
1860                         if (userName[0] == '\0') {
1861                                 avo_get_user(userName, NULL);
1862                         }
1863                         if (hostName[0] == '\0') {
1864                                 strcpy(hostName, avo_hostname());
1865                         }
1866                         send_rsrc_info_msg(1, hostName, userName);
1867                         sent_rsrc_info_msg = 1;
1868                 }
1869                 send_job_start_msg(line);
1870                 job_result_msg = new Avo_MToolJobResultMsg();


1913                                                 getpid(),
1914                                                 file_number++);
1915 
1916                                 int tmp_fd = mkstemp(mbstring);
1917                                 if(tmp_fd) {
1918                                         (void) close(tmp_fd);
1919                                 }
1920 
1921                                 stdout_file = strdup(mbstring);
1922                                 stderr_file = NULL;
1923                                 child_pid = pollResults(stdout_file,
1924                                                         (char *)NULL,
1925                                                         (char *)NULL);
1926                         );
1927                         /* Do assignment if command line prefixed with "=" */
1928                         if (rule->assign) {
1929                                 result = build_ok;
1930                                 do_assign(rule->command_line, target);
1931                         } else if (report_dependencies_level == 0) {
1932                                 /* Execute command line. */
1933 #ifdef DISTRIBUTED
1934                                 setvar_envvar((Avo_DoJobMsg *)NULL);
1935 #else
1936                                 setvar_envvar();
1937 #endif
1938                                 result = dosys(rule->command_line,
1939                                                (Boolean) rule->ignore_error,
1940                                                (Boolean) rule->make_refd,
1941                                                /* ds 98.04.23 bug #4085164. make should always show error messages */
1942                                                false,
1943                                                /* BOOLEAN(rule->silent &&
1944                                                        rule->ignore_error), */
1945                                                (Boolean) rule->always_exec,
1946                                                target,
1947                                                send_mtool_msgs);
1948                                 check_state(temp_file_name);
1949                         }
1950                         SEND_MTOOL_MSG(
1951                                 append_job_result_msg(job_result_msg);
1952                                 if (child_pid > 0) {
1953                                         kill(child_pid, SIGUSR1);
1954                                         while (!((waitpid(child_pid, 0, 0) == -1)
1955                                                 && (errno == ECHILD)));
1956                                 }
1957                                 child_pid = 0;


2021                         spro->body.macro.value = NULL;
2022                 }
2023         }
2024         spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
2025         if(spro) {
2026                 char *val = spro->body.env_mem.value;
2027                 if(val != NULL) {
2028                         /* 
2029                          * Do not return memory allocated for SUNPRO_DEPENDENCIES
2030                          * It will be returned in setvar_daemon() in macro.cc 
2031                          */
2032                         //      retmem_mb(val);
2033                         spro->body.env_mem.value = NULL;
2034                 }
2035         }
2036         
2037         return result;
2038 }
2039 
2040 
2041 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
2042 
2043 /*
2044  * Create and send an Avo_MToolRsrcInfoMsg.
2045  */
2046 void
2047 send_rsrc_info_msg(int max_jobs, char *hostname, char *username)
2048 {
2049         static int              first = 1;
2050         Avo_MToolRsrcInfoMsg    *msg;
2051         RWSlistCollectables     server_list;
2052         Avo_ServerState         *server_state;
2053         RWCollectable           *xdr_msg;
2054 
2055         if (!first) {
2056                 return;
2057         }
2058         first = 0;
2059 
2060         create_xdrs_ptr();
2061 
2062         server_state = new Avo_ServerState(max_jobs, hostname, username);
2063         server_list.append(server_state);
2064         msg = new Avo_MToolRsrcInfoMsg(&server_list);
2065 
2066         xdr_msg = (RWCollectable *)msg;
2067         xdr(get_xdrs_ptr(), xdr_msg);
2068         (void) fflush(get_mtool_msgs_fp());
2069 
2070         delete server_state;
2071         delete msg;
2072 }
2073 
2074 /*
2075  * Create and send an Avo_MToolJobStartMsg.
2076  */
2077 void
2078 send_job_start_msg(Property line)
2079 {
2080         int                     cmd_options = 0;
2081         Avo_MToolJobStartMsg    *msg;
2082         Cmd_line                rule;
2083         Name                    target = line->body.line.target;
2084         RWCollectable           *xdr_msg;
2085 
2086         if (userName[0] == '\0') {
2087                 avo_get_user(userName, NULL);
2088         }
2089         if (hostName[0] == '\0') {
2090                 strcpy(hostName, avo_hostname());
2091         }
2092 
2093         msg = new Avo_MToolJobStartMsg();
2094         msg->setJobId(++job_msg_id);
2095         msg->setTarget(AVO_STRDUP(target->string_mb));
2096         msg->setHost(AVO_STRDUP(hostName));
2097         msg->setUser(AVO_STRDUP(userName));
2098 
2099         for (rule = line->body.line.command_used;
2100              rule != NULL;
2101              rule = rule->next) {
2102                 if (posix && (touch || quest) && !rule->always_exec) {
2103                         continue;
2104                 }
2105                 if (vpath_defined) {
2106                         rule->command_line =
2107                           vpath_translation(rule->command_line);
2108                 }
2109                 cmd_options = 0;
2110                 if (rule->ignore_error || ignore_errors) {
2111                         cmd_options |= ignore_mask;
2112                 }
2113                 if (rule->silent || silent) {
2114                         cmd_options |= silent_mask;
2115                 }
2116                 if (rule->command_line->meta) {
2117                         cmd_options |= meta_mask;
2118                 }
2119                 if (!touch && (rule->command_line->hash.length > 0)) {
2120                         msg->appendCmd(new Avo_DmakeCommand(rule->command_line->string_mb, cmd_options));
2121                 }
2122         }
2123 
2124         xdr_msg = (RWCollectable*) msg;
2125         xdr(&xdrs, xdr_msg);
2126         (void) fflush(mtool_msgs_fp);
2127 
2128 /* tolik, 08/39/2002.
2129    I commented out this code because it causes using unallocated memory.
2130         delete msg;
2131 */
2132 }
2133 
2134 /*
2135  * Append the stdout/err to Avo_MToolJobResultMsg.
2136  */
2137 static void
2138 append_job_result_msg(Avo_MToolJobResultMsg *job_result_msg)
2139 {
2140         FILE            *fp;
2141         char            line[MAXPATHLEN];
2142         char            stdout_file2[MAXPATHLEN];
2143 
2144         if (stdout_file != NULL) {
2145                 fp = fopen(stdout_file, "r");
2146                 if (fp == NULL) {
2147                         /* Hmmm... what should we do here? */
2148                         warning(catgets(catd, 1, 326, "fopen() of stdout_file failed. Output may be lost"));
2149                         return;
2150                 }
2151                 while (fgets(line, MAXPATHLEN, fp) != NULL) {
2152                         if (line[strlen(line) - 1] == '\n') {
2153                                 line[strlen(line) - 1] = '\0';
2154                         }
2155                         job_result_msg->appendOutput(AVO_STRDUP(line));
2156                 }
2157                 (void) fclose(fp);
2158                 us_sleep(STAT_RETRY_SLEEP_TIME);
2159         } else {
2160                 /* Hmmm... stdout_file shouldn't be NULL */
2161                 warning(catgets(catd, 1, 327, "Internal stdout_file variable shouldn't be NULL. Output may be lost"));
2162         }
2163 }
2164 #endif /* TEAMWARE_MAKE_CMN */
2165 
2166 /*
2167  *      vpath_translation(cmd)
2168  *
2169  *      Translates one command line by
2170  *      checking each word. If the word has an alias it is translated.
2171  *
2172  *      Return value:
2173  *                              The translated command
2174  *
2175  *      Parameters:
2176  *              cmd             Command to translate
2177  *
2178  *      Global variables used:
2179  */
2180 Name
2181 vpath_translation(register Name cmd)
2182 {
2183         wchar_t                 buffer[STRING_BUFFER_LENGTH];
2184         String_rec              new_cmd;


2776  *
2777  *      Parameters:
2778  *              line            The command line to update
2779  *              target          The target we are touching
2780  *              result          Initial value for the result we return
2781  *
2782  *      Global variables used:
2783  *              do_not_exec_rule Indicates that -n is on
2784  *              silent          Do not echo commands
2785  */
2786 static Doname
2787 touch_command(register Property line, register Name target, Doname result)
2788 {
2789         Name                    name;
2790         register Chain          target_group;
2791         String_rec              touch_string;
2792         wchar_t                 buffer[MAXPATHLEN];
2793         Name                    touch_cmd;
2794         Cmd_line                rule;
2795 
2796 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
2797         Avo_MToolJobResultMsg   *job_result_msg;
2798         RWCollectable           *xdr_msg;
2799         int                     child_pid = 0;
2800         wchar_t                 string[MAXPATHLEN];
2801         char                    mbstring[MAXPATHLEN];
2802         int                     filed;
2803 #endif
2804 
2805         SEND_MTOOL_MSG(
2806                 if (!sent_rsrc_info_msg) {
2807                         if (userName[0] == '\0') {
2808                                 avo_get_user(userName, NULL);
2809                         }
2810                         if (hostName[0] == '\0') {
2811                                 strcpy(hostName, avo_hostname());
2812                         }
2813                         send_rsrc_info_msg(1, hostName, userName);
2814                         sent_rsrc_info_msg = 1;
2815                 }
2816                 send_job_start_msg(line);
2817                 job_result_msg = new Avo_MToolJobResultMsg();
2818         );
2819         for (name = target, target_group = NULL; name != NULL;) {
2820                 if (!name->is_member) {
2821                         /*
2822                          * Build a touch command that can be passed
2823                          * to dosys(). If KEEP_STATE is on, "make -t"


3443                                         if (*p++ == dependency->name) {
3444                                                 /* If we can find it on the */
3445                                                 /* saved list of autos we */
3446                                                 /* are OK  */
3447                                                 goto not_new;
3448                                         }
3449                                 }
3450                                 /* But if we scan over the old list */
3451                                 /* of auto. without finding it it is */
3452                                 /* new and we must check it */
3453                                 return true;
3454                         }
3455                 not_new:;
3456                 }
3457                 return false;
3458         } else {
3459                 return false;
3460         }
3461 }
3462 
3463 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
3464 void
3465 create_xdrs_ptr(void)
3466 {
3467         static int      xdrs_init = 0;
3468 
3469         if (!xdrs_init) {
3470                 xdrs_init = 1;
3471                 mtool_msgs_fp = fdopen(mtool_msgs_fd, "a");
3472                 xdrstdio_create(&xdrs,
3473                                 mtool_msgs_fp,
3474                                 XDR_ENCODE);
3475         }
3476 }
3477 
3478 XDR *
3479 get_xdrs_ptr(void)
3480 {
3481         return &xdrs;
3482 }
3483 
3484 FILE *
3485 get_mtool_msgs_fp(void)
3486 {
3487         return mtool_msgs_fp;
3488 }
3489 
3490 int
3491 get_job_msg_id(void)
3492 {
3493         return job_msg_id;
3494 }
3495 
3496 // Continuously poll and show the results of remotely executing a job,
3497 // i.e., output the stdout and stderr files.
3498 
3499 static int
3500 pollResults(char *outFn, char *errFn, char *hostNm)
3501 {
3502         int             child;
3503 
3504         child = fork();
3505         switch (child) {
3506         case -1:
3507                 break;
3508         case 0:
3509                 enable_interrupt((void (*) (int))SIG_DFL);
3510                 (void) sigset(SIGUSR1, Avo_PollResultsAction_Sigusr1Handler);
3511                 pollResultsAction(outFn, errFn);
3512 
3513                 exit(0);
3514                 break;
3515         default:
3516                 break;
3517         }
3518         return child;
3519 }
3520 
3521 // This is the PollResultsAction SIGUSR1 handler.
3522 
3523 static bool_t pollResultsActionTimeToFinish = FALSE;
3524 
3525 extern "C" void
3526 Avo_PollResultsAction_Sigusr1Handler(int foo)
3527 {
3528         pollResultsActionTimeToFinish = TRUE;
3529 }
3530 
3531 static void
3532 pollResultsAction(char *outFn, char *errFn)
3533 {
3534         int                     fd;
3535         time_t                  file_time = 0;
3536         long                    file_time_nsec = 0;
3537         struct stat             statbuf;
3538         int                     stat_rc;
3539 
3540         // Keep stat'ing until file exists.
3541         while (((stat_rc = stat(outFn, &statbuf)) != 0) &&
3542                (errno == ENOENT) && 
3543                !pollResultsActionTimeToFinish) {
3544                 us_sleep(STAT_RETRY_SLEEP_TIME);
3545         }
3546         // The previous stat() could be failed due to EINTR
3547         // So one more try is needed
3548         if (stat_rc != 0 && stat(outFn, &statbuf) != 0) {
3549                 // stat() failed
3550                 warning(NOCATGETS("Internal error: stat(\"%s\", ...) failed: %s\n"),
3551                         outFn, strerror(errno));
3552                 exit(1);
3553         }
3554 
3555         if ((fd = open(outFn, O_RDONLY)) < 0
3556                 && (errno != EINTR || (fd = open(outFn, O_RDONLY)) < 0)) {
3557                 // open() failed
3558                 warning(NOCATGETS("Internal error: open(\"%s\", O_RDONLY) failed: %s\n"),
3559                         outFn, strerror(errno));
3560                 exit(1);
3561         }
3562 
3563         while (!pollResultsActionTimeToFinish && stat(outFn, &statbuf) == 0) {
3564                 if ((statbuf.st_mtim.tv_sec > file_time) ||
3565                     ((statbuf.st_mtim.tv_sec == file_time) &&
3566                     (statbuf.st_mtim.tv_nsec > file_time_nsec))
3567                    ) {
3568                         file_time = statbuf.st_mtim.tv_sec;
3569                         file_time_nsec = statbuf.st_mtim.tv_nsec;
3570                         rxmGetNextResultsBlock(fd);
3571                 }
3572                 us_sleep(STAT_RETRY_SLEEP_TIME);
3573         }
3574         // Check for the rest of output
3575         rxmGetNextResultsBlock(fd);
3576 
3577         (void) close(fd);
3578 }
3579 
3580 static void
3581 rxmGetNextResultsBlock(int fd)
3582 {
3583         size_t                  to_read = 8 * 1024;
3584         ssize_t                 bytes_read;
3585         ssize_t                 bytes_written;
3586         char                    results_buf[8 * 1024];
3587         sigset_t                newset;
3588         sigset_t                oldset;
3589 
3590         // Read some more from the output/results file.
3591         // Hopefully the kernel managed to prefetch the stuff.
3592         bytes_read = read(fd, results_buf, to_read);
3593         while (bytes_read > 0) {
3594                 AVO_BLOCK_INTERUPTS;
3595                 bytes_written = write(1, results_buf, bytes_read);
3596                 AVO_UNBLOCK_INTERUPTS;
3597                 if (bytes_written != bytes_read) {
3598                         // write() failed
3599                         warning(NOCATGETS("Internal error: write(1, ...) failed: %s\n"),
3600                                 strerror(errno));
3601                         exit(1);
3602                 }
3603                 bytes_read = read(fd, results_buf, to_read);
3604         }
3605 }
3606 
3607 // Generic, interruptable microsecond resolution sleep member function.
3608 
3609 static int
3610 us_sleep(unsigned int nusecs)
3611 {
3612         struct pollfd dummy;
3613         int timeout;
3614 
3615         if ((timeout = nusecs/1000) <= 0) {
3616                 timeout = 1;
3617         }
3618         return poll(&dummy, 0, timeout);
3619 }
3620 #endif /* TEAMWARE_MAKE_CMN */
3621 
3622 // Recursively delete each of the Chain struct on the chain.
3623 
3624 static void
3625 delete_query_chain(Chain ch)
3626 {
3627         if (ch == NULL) {
3628                 return;
3629         } else {
3630                 delete_query_chain(ch->next);
3631                 retmem_mb((char *) ch);
3632         }
3633 }
3634 
3635 Doname
3636 target_can_be_built(register Name target) {
3637         Doname          result = build_dont_know;
3638         Name            true_target = target;
3639         Property        line;
3640 




  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      doname.c
  28  *
  29  *      Figure out which targets are out of date and rebuild them
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <alloca.h>               /* alloca() */
  36 










  37 
  38 #include <fcntl.h>
  39 #include <mk/defs.h>
  40 #include <mksh/i18n.h>            /* get_char_semantics_value() */
  41 #include <mksh/macro.h>           /* getvar(), expand_value() */
  42 #include <mksh/misc.h>            /* getmem() */
  43 #include <poll.h>
  44 
  45 
  46 #include <signal.h>
  47 
  48 #       include <stropts.h>
  49 
  50 #include <sys/errno.h>
  51 #include <sys/stat.h>
  52 #include <sys/types.h>
  53 #include <sys/utsname.h>  /* uname() */
  54 #include <sys/wait.h>
  55 #include <unistd.h>               /* close() */
  56 
  57 /*
  58  * Defined macros
  59  */
  60 #       define LOCALHOST "localhost"
  61 
  62 #define MAXRULES 100
  63 






  64 #define SEND_MTOOL_MSG(cmds) 

  65 
  66 // Sleep for .1 seconds between stat()'s
  67 const int       STAT_RETRY_SLEEP_TIME = 100000;
  68 
  69 /*
  70  * typedefs & structs
  71  */
  72 
  73 /*
  74  * Static variables
  75  */
  76 static char     hostName[MAXNAMELEN] = "";
  77 static char     userName[MAXNAMELEN] = "";
  78 





  79 
  80 static int      second_pass = 0;
  81 
  82 /*
  83  * File table of contents
  84  */
  85 extern  Doname          doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
  86 extern  Doname          doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
  87 static  Boolean         check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
  88 void            dynamic_dependencies(Name target);
  89 static  Doname          run_command(register Property line, Boolean print_machine);
  90 extern  Doname          execute_serial(Property line);
  91 extern  Name            vpath_translation(register Name cmd);
  92 extern  void            check_state(Name temp_file_name);
  93 static  void            read_dependency_file(register Name filename);
  94 static  void            check_read_state_file(void);
  95 static  void            do_assign(register Name line, register Name target);
  96 static  void            build_command_strings(Name target, register Property line);
  97 static  Doname          touch_command(register Property line, register Name target, Doname result);
  98 extern  void            update_target(Property line, Doname result);
  99 static  Doname          sccs_get(register Name target, register Property *command);
 100 extern  void            read_directory_of_file(register Name file);
 101 static  void            add_pattern_conditionals(register Name target);
 102 extern  void            set_locals(register Name target, register Property old_locals);
 103 extern  void            reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
 104 extern  Boolean         check_auto_dependencies(Name target, int auto_count, Name *automatics);
 105 static  void            delete_query_chain(Chain ch);
 106 
 107 // From read2.cc
 108 extern  Name            normalize_name(register wchar_t *name_string, register int length);
 109 
 110 








 111 
 112 /*
 113  * DONE.
 114  *
 115  *      doname_check(target, do_get, implicit, automatic)
 116  *
 117  *      Will call doname() and then inspect the return value
 118  *
 119  *      Return value:
 120  *                              Indication if the build failed or not
 121  *
 122  *      Parameters:
 123  *              target          The target to build
 124  *              do_get          Passed thru to doname()
 125  *              implicit        Passed thru to doname()
 126  *              automatic       Are we building a hidden dependency?
 127  *
 128  *      Global variables used:
 129  *              build_failed_seen       Set if -k is on and error occurs
 130  *              continue_after_error    Indicates that -k is on


 972              dependency != NULL;
 973              dependency = dependency->next) {
 974                 Boolean this_dependency_changed = false;
 975 
 976                 if (!dependency->automatic &&
 977                     (rechecking_target || target->rechecking_target)) {
 978                         /*
 979                          * We only bother with the autos when rechecking
 980                          */
 981                         continue;
 982                 }
 983 
 984                 if (dependency->name == wait_name) {
 985                         /*
 986                          * The special target .WAIT means finish all of
 987                          * the prior dependencies before continuing.
 988                          */
 989                         if (dependencies_running) {
 990                                 break;
 991                         }










 992                 } else {
 993                         timestruc_t     depe_time = file_doesnt_exist;
 994 
 995 
 996                         if (true_target->is_member) {
 997                                 depe_time = exists(dependency->name);
 998                         }
 999                         if (dependency->built ||
1000                             (dependency->name->state == build_failed)) {
1001                                 dep_result = (Doname) dependency->name->state;
1002                         } else {
1003                                 dep_result = doname_check(dependency->name,
1004                                                           do_get,
1005                                                           false,
1006                                                           (Boolean) dependency->automatic);
1007                         }
1008                         if (true_target->is_member || dependency->name->is_member) {
1009                                 /* should compare only secs, cause lib members does not have nsec time resolution */
1010                                 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
1011                                         this_dependency_changed =


1787  *      Return value:
1788  *                              The result of the command build
1789  *
1790  *      Parameters:     
1791  *              line            The command to execute
1792  *
1793  *      Static variables used:
1794  *
1795  *      Global variables used:
1796  *              continue_after_error -k flag
1797  *              do_not_exec_rule -n flag
1798  *              report_dependencies -P flag
1799  *              silent          Don't echo commands before executing
1800  *              temp_file_name  Temp file for auto dependencies
1801  *              vpath_defined   If true, translate path for command
1802  */
1803 Doname
1804 execute_serial(Property line)
1805 {
1806         int                     child_pid = 0;




1807         Boolean                 printed_serial;
1808         Doname                  result = build_ok;
1809         Cmd_line                rule, cmd_tail, command = NULL;
1810         char                    mbstring[MAXPATHLEN];
1811         int                     filed;
1812         Name                    target = line->body.line.target;
1813 
1814         SEND_MTOOL_MSG(
1815                 if (!sent_rsrc_info_msg) {
1816                         if (userName[0] == '\0') {
1817                                 avo_get_user(userName, NULL);
1818                         }
1819                         if (hostName[0] == '\0') {
1820                                 strcpy(hostName, avo_hostname());
1821                         }
1822                         send_rsrc_info_msg(1, hostName, userName);
1823                         sent_rsrc_info_msg = 1;
1824                 }
1825                 send_job_start_msg(line);
1826                 job_result_msg = new Avo_MToolJobResultMsg();


1869                                                 getpid(),
1870                                                 file_number++);
1871 
1872                                 int tmp_fd = mkstemp(mbstring);
1873                                 if(tmp_fd) {
1874                                         (void) close(tmp_fd);
1875                                 }
1876 
1877                                 stdout_file = strdup(mbstring);
1878                                 stderr_file = NULL;
1879                                 child_pid = pollResults(stdout_file,
1880                                                         (char *)NULL,
1881                                                         (char *)NULL);
1882                         );
1883                         /* Do assignment if command line prefixed with "=" */
1884                         if (rule->assign) {
1885                                 result = build_ok;
1886                                 do_assign(rule->command_line, target);
1887                         } else if (report_dependencies_level == 0) {
1888                                 /* Execute command line. */



1889                                 setvar_envvar();

1890                                 result = dosys(rule->command_line,
1891                                                (Boolean) rule->ignore_error,
1892                                                (Boolean) rule->make_refd,
1893                                                /* ds 98.04.23 bug #4085164. make should always show error messages */
1894                                                false,
1895                                                /* BOOLEAN(rule->silent &&
1896                                                        rule->ignore_error), */
1897                                                (Boolean) rule->always_exec,
1898                                                target,
1899                                                send_mtool_msgs);
1900                                 check_state(temp_file_name);
1901                         }
1902                         SEND_MTOOL_MSG(
1903                                 append_job_result_msg(job_result_msg);
1904                                 if (child_pid > 0) {
1905                                         kill(child_pid, SIGUSR1);
1906                                         while (!((waitpid(child_pid, 0, 0) == -1)
1907                                                 && (errno == ECHILD)));
1908                                 }
1909                                 child_pid = 0;


1973                         spro->body.macro.value = NULL;
1974                 }
1975         }
1976         spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1977         if(spro) {
1978                 char *val = spro->body.env_mem.value;
1979                 if(val != NULL) {
1980                         /* 
1981                          * Do not return memory allocated for SUNPRO_DEPENDENCIES
1982                          * It will be returned in setvar_daemon() in macro.cc 
1983                          */
1984                         //      retmem_mb(val);
1985                         spro->body.env_mem.value = NULL;
1986                 }
1987         }
1988         
1989         return result;
1990 }
1991 
1992 




























































































































1993 
1994 /*
1995  *      vpath_translation(cmd)
1996  *
1997  *      Translates one command line by
1998  *      checking each word. If the word has an alias it is translated.
1999  *
2000  *      Return value:
2001  *                              The translated command
2002  *
2003  *      Parameters:
2004  *              cmd             Command to translate
2005  *
2006  *      Global variables used:
2007  */
2008 Name
2009 vpath_translation(register Name cmd)
2010 {
2011         wchar_t                 buffer[STRING_BUFFER_LENGTH];
2012         String_rec              new_cmd;


2604  *
2605  *      Parameters:
2606  *              line            The command line to update
2607  *              target          The target we are touching
2608  *              result          Initial value for the result we return
2609  *
2610  *      Global variables used:
2611  *              do_not_exec_rule Indicates that -n is on
2612  *              silent          Do not echo commands
2613  */
2614 static Doname
2615 touch_command(register Property line, register Name target, Doname result)
2616 {
2617         Name                    name;
2618         register Chain          target_group;
2619         String_rec              touch_string;
2620         wchar_t                 buffer[MAXPATHLEN];
2621         Name                    touch_cmd;
2622         Cmd_line                rule;
2623 








2624 
2625         SEND_MTOOL_MSG(
2626                 if (!sent_rsrc_info_msg) {
2627                         if (userName[0] == '\0') {
2628                                 avo_get_user(userName, NULL);
2629                         }
2630                         if (hostName[0] == '\0') {
2631                                 strcpy(hostName, avo_hostname());
2632                         }
2633                         send_rsrc_info_msg(1, hostName, userName);
2634                         sent_rsrc_info_msg = 1;
2635                 }
2636                 send_job_start_msg(line);
2637                 job_result_msg = new Avo_MToolJobResultMsg();
2638         );
2639         for (name = target, target_group = NULL; name != NULL;) {
2640                 if (!name->is_member) {
2641                         /*
2642                          * Build a touch command that can be passed
2643                          * to dosys(). If KEEP_STATE is on, "make -t"


3263                                         if (*p++ == dependency->name) {
3264                                                 /* If we can find it on the */
3265                                                 /* saved list of autos we */
3266                                                 /* are OK  */
3267                                                 goto not_new;
3268                                         }
3269                                 }
3270                                 /* But if we scan over the old list */
3271                                 /* of auto. without finding it it is */
3272                                 /* new and we must check it */
3273                                 return true;
3274                         }
3275                 not_new:;
3276                 }
3277                 return false;
3278         } else {
3279                 return false;
3280         }
3281 }
3282 






























































































































































3283 
3284 // Recursively delete each of the Chain struct on the chain.
3285 
3286 static void
3287 delete_query_chain(Chain ch)
3288 {
3289         if (ch == NULL) {
3290                 return;
3291         } else {
3292                 delete_query_chain(ch->next);
3293                 retmem_mb((char *) ch);
3294         }
3295 }
3296 
3297 Doname
3298 target_can_be_built(register Name target) {
3299         Doname          result = build_dont_know;
3300         Name            true_target = target;
3301         Property        line;
3302