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