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 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * mksh.cc
29 *
30 * Execute the command(s) of one Make or DMake rule
31 */
32
33 /*
34 * Included files
35 */
36 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) /* tolik */
37 # include <avo/util.h>
38 #endif
39
40 #include <mksh/dosys.h> /* redirect_io() */
41 #include <mksh/misc.h> /* retmem() */
42 #include <mksh/mksh.h>
43 #include <mksdmsi18n/mksdmsi18n.h>
44 #include <errno.h>
45 #include <signal.h>
46
47
48 /*
49 * Workaround for NFS bug. Sometimes, when running 'chdir' on a remote
50 * dmake server, it fails with "Stale NFS file handle" error.
51 * The second attempt seems to work.
52 */
53 int
54 my_chdir(char * dir) {
55 int res = chdir(dir);
56 if (res != 0 && (errno == ESTALE || errno == EAGAIN)) {
57 /* Stale NFS file handle. Try again */
58 res = chdir(dir);
59 }
60 return res;
61 }
62
63
64 /*
65 * File table of contents
66 */
67 static void change_sunpro_dependencies_value(char *oldpath, char *newpath);
68 static void init_mksh_globals(char *shell);
69 static void set_env_vars(char *env_list[]);
70
71 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
72 /*
73 * Execute the command(s) of one Make or DMake rule
74 */
75 int
76 do_job(Avo_DmakeCommand *cmd_list[], char *env_list[], char *stdout_file, char *stderr_file, char *cwd, char *cnwd, int ignore, int silent, pathpt vroot_path, char *shell, int nice_prio)
77 {
78 Boolean always_exec_flag;
79 char *cmd;
80 Avo_DmakeCommand **cmd_list_p;
81 Name command;
82 Boolean do_not_exec_flag;
83 Boolean ignore_flag;
84 int length;
85 Boolean make_refd_flag;
86 Boolean meta_flag;
87 char pathname[MAXPATHLEN];
88 Doname result;
89 Boolean silent_flag;
90 wchar_t *tmp_wcs_buffer;
91
92 if ((childPid = fork()) < 0) { /* error */
93 ;
94 } else if (childPid > 0) { /* parent */
95 ;
96 } else { /* child, mksh */
97 (void) sigset(SIGCHLD, SIG_DFL);
98 enable_interrupt(handle_interrupt_mksh);
99 /* set environment variables */
100 set_env_vars(env_list);
101 /* redirect stdout and stderr to temp files */
102 dup2(1, 2); // Because fatal_mksh() prints error messages into
103 // stderr but dmake uses stderr for XDR communications
104 // and stdout for errors messages.
105 redirect_io(stdout_file, stderr_file);
106 /* try cd'ing to cwd */
107 if (my_chdir(cwd) != 0) {
108 /* try the netpath machine:pathname */
109 if (!avo_netpath_to_path(cnwd, pathname)) {
110 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 137, "`cd %s' failed, and conversion of %s to automounter pathname also failed: %s"), cwd, cnwd, strerror(errno));
111 } else if (my_chdir(pathname) != 0) {
112 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 138, "`cd %s' and `cd %s' both failed: %s"), cwd, pathname, strerror(errno));
113 }
114 /*
115 * change the value of SUNPRO_DEPENDENCIES
116 * to the new path.
117 */
118 change_sunpro_dependencies_value(cwd, pathname);
119 }
120 init_mksh_globals(shell);
121 for (cmd_list_p = cmd_list;
122 *cmd_list_p != (Avo_DmakeCommand *) NULL;
123 cmd_list_p++) {
124 if ((*cmd_list_p)->ignore()) {
125 ignore_flag = true;
126 } else {
127 ignore_flag = false;
128 }
129 if ((*cmd_list_p)->silent()) {
130 silent_flag = true;
131 } else {
132 silent_flag = false;
133 }
134 /*
135 if ((*cmd_list_p)->always_exec()) {
136 always_exec_flag = true;
137 } else {
138 always_exec_flag = false;
139 }
140 */
141 always_exec_flag = false;
142 if ((*cmd_list_p)->meta()) {
143 meta_flag = true;
144 } else {
145 meta_flag = false;
146 }
147 if ((*cmd_list_p)->make_refd()) {
148 make_refd_flag = true;
149 } else {
150 make_refd_flag = false;
151 }
152 if ((*cmd_list_p)->do_not_exec()) {
153 do_not_exec_flag = true;
154 } else {
155 do_not_exec_flag = false;
156 }
157 do_not_exec_rule = do_not_exec_flag;
158 cmd = (*cmd_list_p)->getCmd();
159 if ((length = strlen(cmd)) >= MAXPATHLEN) {
160 tmp_wcs_buffer = ALLOC_WC(length + 1);
161 (void) mbstowcs(tmp_wcs_buffer, cmd, length + 1);
162 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
163 retmem(tmp_wcs_buffer);
164 } else {
165 MBSTOWCS(wcs_buffer, cmd);
166 command = GETNAME(wcs_buffer, FIND_LENGTH);
167 }
168 if ((command->hash.length > 0) &&
169 (!silent_flag || do_not_exec_flag)) {
170 (void) printf("%s\n", command->string_mb);
171 }
172 result = dosys_mksh(command,
173 ignore_flag,
174 make_refd_flag,
175 false, /* bugs #4085164 & #4990057 */
176 /* BOOLEAN(silent_flag && ignore_flag), */
177 always_exec_flag,
178 (Name) NULL,
179 false,
180 NULL,
181 NULL,
182 vroot_path,
183 nice_prio);
184 if (result == build_failed) {
185
186 #ifdef PRINT_EXIT_STATUS
187 warning_mksh(NOCATGETS("I'm in do_job(), and dosys_mksh() returned result of build_failed."));
188 #endif
189
190 if (silent_flag) {
191 (void) printf(catgets(libmksdmsi18n_catd, 1, 139, "The following command caused the error:\n%s\n"),
192 command->string_mb);
193 }
194 if (!ignore_flag && !ignore) {
195
196 #ifdef PRINT_EXIT_STATUS
197 warning_mksh(NOCATGETS("I'm in do_job(), and dosys_mksh() returned result of build_failed, exiting 1."));
198 #endif
199
200 exit(1);
201 }
202 }
203 }
204
205 #ifdef PRINT_EXIT_STATUS
206 warning_mksh(NOCATGETS("I'm in do_job(), exiting 0."));
207 #endif
208
209 exit(0);
210 }
211 return childPid;
212 }
213 #endif /* TEAMWARE_MAKE_CMN */
214
215 static void
216 set_env_vars(char *env_list[])
217 {
218 char **env_list_p;
219
220 for (env_list_p = env_list;
221 *env_list_p != (char *) NULL;
222 env_list_p++) {
223 putenv(*env_list_p);
224 }
225 }
226
227 static void
228 init_mksh_globals(char *shell)
229 {
230 /*
231 MBSTOWCS(wcs_buffer, NOCATGETS("SHELL"));
232 shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
233 MBSTOWCS(wcs_buffer, shell);
234 (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
235 */
236 char * dmake_shell;
237 if ((dmake_shell = getenv(NOCATGETS("DMAKE_SHELL"))) == NULL) {
238 dmake_shell = shell;
239 }
240 MBSTOWCS(wcs_buffer, dmake_shell);
241 shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
242 }
243
244 /*
245 * Change the pathname in the value of the SUNPRO_DEPENDENCIES env variable
246 * from oldpath to newpath.
247 */
248 static void
249 change_sunpro_dependencies_value(char *oldpath, char *newpath)
250 {
251 char buf[MAXPATHLEN];
252 static char *env;
253 int length;
254 int oldpathlen;
255 char *sp_dep_value;
256
257 /* check if SUNPRO_DEPENDENCIES is set in the environment */
258 if ((sp_dep_value = getenv(NOCATGETS("SUNPRO_DEPENDENCIES"))) != NULL) {
259 oldpathlen = strlen(oldpath);
260 /* check if oldpath is indeed in the value of SUNPRO_DEPENDENCIES */
261 if (strncmp(oldpath, sp_dep_value, oldpathlen) == 0) {
262 (void) sprintf(buf,
263 "%s%s",
264 newpath,
265 sp_dep_value + oldpathlen);
266 length = 2 +
267 strlen(NOCATGETS("SUNPRO_DEPENDENCIES")) +
268 strlen(buf);
269 env = getmem(length);
270 (void) sprintf(env,
271 "%s=%s",
272 NOCATGETS("SUNPRO_DEPENDENCIES"),
273 buf);
274 (void) putenv(env);
275 }
276 }
277 }
278
279