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