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