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