36 */
37 #ifdef DISTRIBUTED
38 #include <avo/strings.h> /* AVO_STRDUP() */
39 #include <dm/Avo_DoJobMsg.h>
40 #include <dm/Avo_MToolJobResultMsg.h>
41 #endif
42 #include <errno.h> /* errno */
43 #include <fcntl.h>
44 #include <avo/util.h> /* avo_get_user(), avo_hostname() */
45 #include <mk/defs.h>
46 #include <mksh/dosys.h> /* redirect_io() */
47 #include <mksh/macro.h> /* expand_value() */
48 #include <mksh/misc.h> /* getmem() */
49 #include <sys/signal.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <sys/utsname.h>
53 #include <sys/wait.h>
54 #include <unistd.h>
55
56 #ifdef SGE_SUPPORT
57 #include <dmthread/Avo_PathNames.h>
58 #endif
59
60
61 /*
62 * Defined macros
63 */
64 #define MAXRULES 100
65
66 /*
67 * This const should be in avo_dms/include/AvoDmakeCommand.h
68 */
69 const int local_host_mask = 0x20;
70
71
72 /*
73 * typedefs & structs
74 */
75
76
77 /*
78 * Static variables
849 file_number++);
850
851 mktemp(mbstring);
852
853 stdout_file = strdup(mbstring);
854 stderr_file = NULL;
855 #if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR)
856 if (!out_err_same) {
857 (void) sprintf(mbstring,
858 NOCATGETS("%s/dmake.stderr.%d.%d.XXXXXX"),
859 tmpdir,
860 getpid(),
861 file_number++);
862
863 mktemp(mbstring);
864
865 stderr_file = strdup(mbstring);
866 }
867 #endif
868
869 #ifdef SGE_SUPPORT
870 if (grid) {
871 static char *dir4gridscripts = NULL;
872 static char *hostName = NULL;
873 if (dir4gridscripts == NULL) {
874 Name dmakeOdir_name, dmakeOdir_value;
875 Property prop;
876 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
877 dmakeOdir_name = GETNAME(wcs_buffer, FIND_LENGTH);
878 if (((prop = get_prop(dmakeOdir_name->prop, macro_prop)) != NULL) &&
879 ((dmakeOdir_value = prop->body.macro.value) != NULL)) {
880 dir4gridscripts = dmakeOdir_value->string_mb;
881 }
882 dir4gridscripts = Avo_PathNames::pathname_output_directory(dir4gridscripts);
883 hostName = Avo_PathNames::pathname_local_host();
884 }
885 (void) sprintf(script_file,
886 NOCATGETS("%s/dmake.script.%s.%d.%d.XXXXXX"),
887 dir4gridscripts,
888 hostName,
889 getpid(),
890 file_number++);
891 }
892 #endif /* SGE_SUPPORT */
893 process_running = run_rule_commands(local_host, commands);
894
895 return build_running;
896 }
897
898 /*
899 * doname_parallel(target, do_get, implicit)
900 *
901 * Processes the given target and finishes up any parallel
902 * processes left running.
903 *
904 * Return value:
905 * Result of target build
906 *
907 * Parameters:
908 * target Target to build
909 * do_get True if sccs get to be done
910 * implicit True if this is an implicit target
911 */
912 Doname
2033 {
2034 Running rp;
2035
2036 if (target->state != build_running) {
2037 return false;
2038 }
2039 for (rp = running_list;
2040 rp != NULL && target != rp->target;
2041 rp = rp->next);
2042 if (rp == NULL) {
2043 return false;
2044 } else {
2045 return (rp->state == build_running) ? true : false;
2046 }
2047 }
2048
2049 /*
2050 * This function replaces the makesh binary.
2051 */
2052
2053 #ifdef SGE_SUPPORT
2054 #define DO_CHECK(f) if (f <= 0) { \
2055 fprintf(stderr, \
2056 catgets(catd, 1, 347, "Could not write to file: %s: %s\n"), \
2057 script_file, errmsg(errno)); \
2058 _exit(1); \
2059 }
2060 #endif /* SGE_SUPPORT */
2061
2062 static pid_t
2063 run_rule_commands(char *host, char **commands)
2064 {
2065 Boolean always_exec;
2066 Name command;
2067 Boolean ignore;
2068 int length;
2069 Doname result;
2070 Boolean silent_flag;
2071 #ifdef SGE_SUPPORT
2072 wchar_t *wcmd, *tmp_wcs_buffer = NULL;
2073 char *cmd, *tmp_mbs_buffer = NULL;
2074 FILE *scrfp;
2075 Name shell = getvar(shell_name);
2076 #else
2077 wchar_t *tmp_wcs_buffer;
2078 #endif /* SGE_SUPPORT */
2079
2080 childPid = fork();
2081 switch (childPid) {
2082 case -1: /* Error */
2083 fatal(catgets(catd, 1, 337, "Could not fork child process for dmake job: %s"),
2084 errmsg(errno));
2085 break;
2086 case 0: /* Child */
2087 /* To control the processed targets list is not the child's business */
2088 running_list = NULL;
2089 #if defined(REDIRECT_ERR)
2090 if(out_err_same) {
2091 redirect_io(stdout_file, (char*)NULL);
2092 } else {
2093 redirect_io(stdout_file, stderr_file);
2094 }
2095 #else
2096 redirect_io(stdout_file, (char*)NULL);
2097 #endif
2098 #ifdef SGE_SUPPORT
2099 if (grid) {
2100 int fdes = mkstemp(script_file);
2101 if ((fdes < 0) || (scrfp = fdopen(fdes, "w")) == NULL) {
2102 fprintf(stderr,
2103 catgets(catd, 1, 341, "Could not create file: %s: %s\n"),
2104 script_file, errmsg(errno));
2105 _exit(1);
2106 }
2107 if (IS_EQUAL(shell->string_mb, "")) {
2108 shell = shell_name;
2109 }
2110 }
2111 #endif /* SGE_SUPPORT */
2112 for (commands = commands;
2113 (*commands != (char *)NULL);
2114 commands++) {
2115 silent_flag = silent;
2116 ignore = false;
2117 always_exec = false;
2118 while ((**commands == (int) at_char) ||
2119 (**commands == (int) hyphen_char) ||
2120 (**commands == (int) plus_char)) {
2121 if (**commands == (int) at_char) {
2122 silent_flag = true;
2123 }
2124 if (**commands == (int) hyphen_char) {
2125 ignore = true;
2126 }
2127 if (**commands == (int) plus_char) {
2128 always_exec = true;
2129 }
2130 (*commands)++;
2131 }
2132 #ifdef SGE_SUPPORT
2133 if (grid) {
2134 if ((length = strlen(*commands)) >= MAXPATHLEN / 2) {
2135 wcmd = tmp_wcs_buffer = ALLOC_WC(length * 2 + 1);
2136 (void) mbstowcs(tmp_wcs_buffer, *commands, length * 2 + 1);
2137 } else {
2138 MBSTOWCS(wcs_buffer, *commands);
2139 wcmd = wcs_buffer;
2140 cmd = mbs_buffer;
2141 }
2142 wchar_t *from = wcmd + wslen(wcmd);
2143 wchar_t *to = from + (from - wcmd);
2144 *to = (int) nul_char;
2145 while (from > wcmd) {
2146 *--to = *--from;
2147 if (*from == (int) newline_char) { // newline symbols are already quoted
2148 *--to = *--from;
2149 } else if (wschr(char_semantics_char, *from)) {
2150 *--to = (int) backslash_char;
2151 }
2152 }
2153 if (length >= MAXPATHLEN*MB_LEN_MAX/2) { // sizeof(mbs_buffer) / 2
2154 cmd = tmp_mbs_buffer = getmem((length * MB_LEN_MAX * 2) + 1);
2155 (void) wcstombs(tmp_mbs_buffer, to, (length * MB_LEN_MAX * 2) + 1);
2156 } else {
2157 WCSTOMBS(mbs_buffer, to);
2158 cmd = mbs_buffer;
2159 }
2160 char *mbst, *mbend;
2161 if ((length > 0) &&
2162 !silent_flag) {
2163 for (mbst = cmd; (mbend = strstr(mbst, "\\\n")) != NULL; mbst = mbend + 2) {
2164 *mbend = '\0';
2165 DO_CHECK(fprintf(scrfp, NOCATGETS("/usr/bin/printf '%%s\\n' %s\\\\\n"), mbst));
2166 *mbend = '\\';
2167 }
2168 DO_CHECK(fprintf(scrfp, NOCATGETS("/usr/bin/printf '%%s\\n' %s\n"), mbst));
2169 }
2170 if (!do_not_exec_rule ||
2171 !working_on_targets ||
2172 always_exec) {
2173 DO_CHECK(fprintf(scrfp, NOCATGETS("%s -ce %s\n"), shell->string_mb, cmd));
2174 DO_CHECK(fputs(NOCATGETS("__DMAKECMDEXITSTAT=$?\nif [ ${__DMAKECMDEXITSTAT} -ne 0 ]; then\n"), scrfp));
2175 if (ignore) {
2176 DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s ${__DMAKECMDEXITSTAT} %s\n"),
2177 catgets(catd, 1, 343, "\"*** Error code"),
2178 catgets(catd, 1, 344, "(ignored)\"")));
2179 } else {
2180 DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s ${__DMAKECMDEXITSTAT}\n"),
2181 catgets(catd, 1, 342, "\"*** Error code\"")));
2182 }
2183 if (silent_flag) {
2184 DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s\n"),
2185 catgets(catd, 1, 345, "The following command caused the error:")));
2186 for (mbst = cmd; (mbend = strstr(mbst, "\\\n")) != NULL; mbst = mbend + 2) {
2187 *mbend = '\0';
2188 DO_CHECK(fprintf(scrfp, NOCATGETS("\t/usr/bin/printf '%%s\\n' %s\\\\\n"), mbst));
2189 *mbend = '\\';
2190 }
2191 DO_CHECK(fprintf(scrfp, NOCATGETS("\t/usr/bin/printf '%%s\\n' %s\n"), mbst));
2192 }
2193 if (!ignore) {
2194 DO_CHECK(fputs(NOCATGETS("\texit ${__DMAKECMDEXITSTAT}\n"), scrfp));
2195 }
2196 DO_CHECK(fputs(NOCATGETS("fi\n"), scrfp));
2197 }
2198 if (tmp_wcs_buffer) {
2199 retmem_mb(tmp_mbs_buffer);
2200 tmp_mbs_buffer = NULL;
2201 }
2202 if (tmp_wcs_buffer) {
2203 retmem(tmp_wcs_buffer);
2204 tmp_wcs_buffer = NULL;
2205 }
2206 continue;
2207 }
2208 #endif /* SGE_SUPPORT */
2209 if ((length = strlen(*commands)) >= MAXPATHLEN) {
2210 tmp_wcs_buffer = ALLOC_WC(length + 1);
2211 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
2212 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2213 retmem(tmp_wcs_buffer);
2214 } else {
2215 MBSTOWCS(wcs_buffer, *commands);
2216 command = GETNAME(wcs_buffer, FIND_LENGTH);
2217 }
2218 if ((command->hash.length > 0) &&
2219 !silent_flag) {
2220 (void) printf("%s\n", command->string_mb);
2221 }
2222 result = dosys(command,
2223 ignore,
2224 false,
2225 false, /* bugs #4085164 & #4990057 */
2226 /* BOOLEAN(silent_flag && ignore), */
2227 always_exec,
2228 (Name) NULL,
2229 false);
2230 if (result == build_failed) {
2231 if (silent_flag) {
2232 (void) printf(catgets(catd, 1, 152, "The following command caused the error:\n%s\n"), command->string_mb);
2233 }
2234 if (!ignore) {
2235 _exit(1);
2236 }
2237 }
2238 }
2239 #ifndef SGE_SUPPORT
2240 _exit(0);
2241 #else
2242 if (!grid) {
2243 _exit(0);
2244 }
2245 DO_CHECK(fputs(NOCATGETS("exit 0\n"), scrfp));
2246 if (fclose(scrfp) != 0) {
2247 fprintf(stderr,
2248 catgets(catd, 1, 346, "Could not close file: %s: %s\n"),
2249 script_file, errmsg(errno));
2250 _exit(1);
2251 }
2252 {
2253
2254 #define DEFAULT_QRSH_TRIES_NUMBER 1
2255 #define DEFAULT_QRSH_TIMEOUT 0
2256
2257 static char *sge_env_var = NULL;
2258 static int qrsh_tries_number = DEFAULT_QRSH_TRIES_NUMBER;
2259 static int qrsh_timeout = DEFAULT_QRSH_TIMEOUT;
2260 #define SGE_DEBUG
2261 #ifdef SGE_DEBUG
2262 static Boolean do_not_remove = false;
2263 #endif /* SGE_DEBUG */
2264 if (sge_env_var == NULL) {
2265 sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_TRIES"));
2266 if (sge_env_var != NULL) {
2267 qrsh_tries_number = atoi(sge_env_var);
2268 if (qrsh_tries_number < 1 || qrsh_tries_number > 9) {
2269 qrsh_tries_number = DEFAULT_QRSH_TRIES_NUMBER;
2270 }
2271 }
2272 sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_TIMEOUT"));
2273 if (sge_env_var != NULL) {
2274 qrsh_timeout = atoi(sge_env_var);
2275 if (qrsh_timeout <= 0) {
2276 qrsh_timeout = DEFAULT_QRSH_TIMEOUT;
2277 }
2278 } else {
2279 sge_env_var = "";
2280 }
2281 #ifdef SGE_DEBUG
2282 sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_DEBUG"));
2283 if (sge_env_var == NULL) {
2284 sge_env_var = "";
2285 }
2286 if (strstr(sge_env_var, NOCATGETS("noqrsh")) != NULL)
2287 qrsh_tries_number = 0;
2288 if (strstr(sge_env_var, NOCATGETS("donotremove")) != NULL)
2289 do_not_remove = true;
2290 #endif /* SGE_DEBUG */
2291 }
2292 for (int i = qrsh_tries_number; ; i--)
2293 if ((childPid = fork()) < 0) {
2294 fatal(catgets(catd, 1, 348, "Could not fork child process for qrsh job: %s"),
2295 errmsg(errno));
2296 _exit(1);
2297 } else if (childPid == 0) {
2298 enable_interrupt((void (*) (int))SIG_DFL);
2299 if (i > 0) {
2300 static char qrsh_cmd[50+MAXPATHLEN] = NOCATGETS("qrsh -cwd -V -noshell -nostdin /bin/sh ");
2301 static char *fname_ptr = NULL;
2302 static char *argv[] = { NOCATGETS("sh"),
2303 NOCATGETS("-fce"),
2304 qrsh_cmd,
2305 NULL};
2306 if (fname_ptr == NULL) {
2307 fname_ptr = qrsh_cmd + strlen(qrsh_cmd);
2308 }
2309 strcpy(fname_ptr, script_file);
2310 (void) execve(NOCATGETS("/bin/sh"), argv, environ);
2311 } else {
2312 static char *argv[] = { NOCATGETS("sh"),
2313 script_file,
2314 NULL};
2315 (void) execve(NOCATGETS("/bin/sh"), argv, environ);
2316 }
2317 fprintf(stderr,
2318 catgets(catd, 1, 349, "Could not load `qrsh': %s\n"),
2319 errmsg(errno));
2320 _exit(1);
2321 } else {
2322 int status;
2323 pid_t pid;
2324 while ((pid = wait(&status)) != childPid) {
2325 if (pid == -1) {
2326 fprintf(stderr,
2327 catgets(catd, 1, 350, "wait() failed: %s\n"),
2328 errmsg(errno));
2329 _exit(1);
2330 }
2331 }
2332 if (status != 0 && i > 0) {
2333 if (i > 1) {
2334 sleep(qrsh_timeout);
2335 }
2336 continue;
2337 }
2338 #ifdef SGE_DEBUG
2339 if (do_not_remove) {
2340 if (status) {
2341 fprintf(stderr,
2342 NOCATGETS("SGE script failed: %s\n"),
2343 script_file);
2344 }
2345 _exit(status ? 1 : 0);
2346 }
2347 #endif /* SGE_DEBUG */
2348 (void) unlink(script_file);
2349 _exit(status ? 1 : 0);
2350 }
2351 }
2352 #endif /* SGE_SUPPORT */
2353 break;
2354 default:
2355 break;
2356 }
2357 return childPid;
2358 }
2359
2360 static void
2361 maybe_reread_make_state(void)
2362 {
2363 /* Copying dosys()... */
2364 if (report_dependencies_level == 0) {
2365 make_state->stat.time = file_no_time;
2366 (void) exists(make_state);
2367 if (make_state_before == make_state->stat.time) {
2368 return;
2369 }
2370 makefile_type = reading_statefile;
2371 if (read_trace_level > 1) {
2372 trace_reader = true;
|
36 */
37 #ifdef DISTRIBUTED
38 #include <avo/strings.h> /* AVO_STRDUP() */
39 #include <dm/Avo_DoJobMsg.h>
40 #include <dm/Avo_MToolJobResultMsg.h>
41 #endif
42 #include <errno.h> /* errno */
43 #include <fcntl.h>
44 #include <avo/util.h> /* avo_get_user(), avo_hostname() */
45 #include <mk/defs.h>
46 #include <mksh/dosys.h> /* redirect_io() */
47 #include <mksh/macro.h> /* expand_value() */
48 #include <mksh/misc.h> /* getmem() */
49 #include <sys/signal.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <sys/utsname.h>
53 #include <sys/wait.h>
54 #include <unistd.h>
55
56
57
58 /*
59 * Defined macros
60 */
61 #define MAXRULES 100
62
63 /*
64 * This const should be in avo_dms/include/AvoDmakeCommand.h
65 */
66 const int local_host_mask = 0x20;
67
68
69 /*
70 * typedefs & structs
71 */
72
73
74 /*
75 * Static variables
846 file_number++);
847
848 mktemp(mbstring);
849
850 stdout_file = strdup(mbstring);
851 stderr_file = NULL;
852 #if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR)
853 if (!out_err_same) {
854 (void) sprintf(mbstring,
855 NOCATGETS("%s/dmake.stderr.%d.%d.XXXXXX"),
856 tmpdir,
857 getpid(),
858 file_number++);
859
860 mktemp(mbstring);
861
862 stderr_file = strdup(mbstring);
863 }
864 #endif
865
866 process_running = run_rule_commands(local_host, commands);
867
868 return build_running;
869 }
870
871 /*
872 * doname_parallel(target, do_get, implicit)
873 *
874 * Processes the given target and finishes up any parallel
875 * processes left running.
876 *
877 * Return value:
878 * Result of target build
879 *
880 * Parameters:
881 * target Target to build
882 * do_get True if sccs get to be done
883 * implicit True if this is an implicit target
884 */
885 Doname
2006 {
2007 Running rp;
2008
2009 if (target->state != build_running) {
2010 return false;
2011 }
2012 for (rp = running_list;
2013 rp != NULL && target != rp->target;
2014 rp = rp->next);
2015 if (rp == NULL) {
2016 return false;
2017 } else {
2018 return (rp->state == build_running) ? true : false;
2019 }
2020 }
2021
2022 /*
2023 * This function replaces the makesh binary.
2024 */
2025
2026
2027 static pid_t
2028 run_rule_commands(char *host, char **commands)
2029 {
2030 Boolean always_exec;
2031 Name command;
2032 Boolean ignore;
2033 int length;
2034 Doname result;
2035 Boolean silent_flag;
2036 wchar_t *tmp_wcs_buffer;
2037
2038 childPid = fork();
2039 switch (childPid) {
2040 case -1: /* Error */
2041 fatal(catgets(catd, 1, 337, "Could not fork child process for dmake job: %s"),
2042 errmsg(errno));
2043 break;
2044 case 0: /* Child */
2045 /* To control the processed targets list is not the child's business */
2046 running_list = NULL;
2047 #if defined(REDIRECT_ERR)
2048 if(out_err_same) {
2049 redirect_io(stdout_file, (char*)NULL);
2050 } else {
2051 redirect_io(stdout_file, stderr_file);
2052 }
2053 #else
2054 redirect_io(stdout_file, (char*)NULL);
2055 #endif
2056 for (commands = commands;
2057 (*commands != (char *)NULL);
2058 commands++) {
2059 silent_flag = silent;
2060 ignore = false;
2061 always_exec = false;
2062 while ((**commands == (int) at_char) ||
2063 (**commands == (int) hyphen_char) ||
2064 (**commands == (int) plus_char)) {
2065 if (**commands == (int) at_char) {
2066 silent_flag = true;
2067 }
2068 if (**commands == (int) hyphen_char) {
2069 ignore = true;
2070 }
2071 if (**commands == (int) plus_char) {
2072 always_exec = true;
2073 }
2074 (*commands)++;
2075 }
2076 if ((length = strlen(*commands)) >= MAXPATHLEN) {
2077 tmp_wcs_buffer = ALLOC_WC(length + 1);
2078 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
2079 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2080 retmem(tmp_wcs_buffer);
2081 } else {
2082 MBSTOWCS(wcs_buffer, *commands);
2083 command = GETNAME(wcs_buffer, FIND_LENGTH);
2084 }
2085 if ((command->hash.length > 0) &&
2086 !silent_flag) {
2087 (void) printf("%s\n", command->string_mb);
2088 }
2089 result = dosys(command,
2090 ignore,
2091 false,
2092 false, /* bugs #4085164 & #4990057 */
2093 /* BOOLEAN(silent_flag && ignore), */
2094 always_exec,
2095 (Name) NULL,
2096 false);
2097 if (result == build_failed) {
2098 if (silent_flag) {
2099 (void) printf(catgets(catd, 1, 152, "The following command caused the error:\n%s\n"), command->string_mb);
2100 }
2101 if (!ignore) {
2102 _exit(1);
2103 }
2104 }
2105 }
2106 _exit(0);
2107 break;
2108 default:
2109 break;
2110 }
2111 return childPid;
2112 }
2113
2114 static void
2115 maybe_reread_make_state(void)
2116 {
2117 /* Copying dosys()... */
2118 if (report_dependencies_level == 0) {
2119 make_state->stat.time = file_no_time;
2120 (void) exists(make_state);
2121 if (make_state_before == make_state->stat.time) {
2122 return;
2123 }
2124 makefile_type = reading_statefile;
2125 if (read_trace_level > 1) {
2126 trace_reader = true;
|