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