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