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