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