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  *      dosys.cc
  28  *
  29  *      Execute one commandline
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <fcntl.h>                /* open() */
  36 #include <mk/defs.h>
  37 #include <mksh/dosys.h>           /* doshell(), doexec() */
  38 #include <mksh/misc.h>            /* getmem() */
  39 #include <sys/stat.h>             /* open() */
  40 #include <unistd.h>               /* getpid() */
  41 
  42 /*
  43  * Defined macros
  44  */
  45 
  46 /*
  47  * typedefs & structs
  48  */
  49 
  50 /*
  51  * Static variables
  52  */
  53 static  int             filter_file;
  54 static  char            *filter_file_name;
  55 
  56 /*
  57  * File table of contents
  58  */
  59 static  void            redirect_stderr(void);
  60 
  61 /*
  62  *      dosys(command, ignore_error, call_make, silent_error, target)
  63  *
  64  *      Check if command string contains meta chars and dispatch to
  65  *      the proper routine for executing one command line.
  66  *
  67  *      Return value:
  68  *                              Indicates if the command execution failed
  69  *
  70  *      Parameters:
  71  *              command         The command to run
  72  *              ignore_error    Should make abort when an error is seen?
  73  *              call_make       Did command reference $(MAKE) ?
  74  *              silent_error    Should error messages be suppressed for pmake?
  75  *              target          Target we are building
  76  *
  77  *      Global variables used:
  78  *              do_not_exec_rule Is -n on?
  79  *              working_on_targets We started processing real targets
  80  */
  81 Doname
  82 dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err)
  83 {
  84         timestruc_t             before;
  85         register int            length = command->hash.length;
  86         Wstring                 wcb(command);
  87         register wchar_t        *p = wcb.get_string();
  88         register wchar_t        *q;
  89         Doname                  result;
  90 
  91         /* Strip spaces from head of command string */
  92         while (iswspace(*p)) {
  93                 p++, length--;
  94         }
  95         if (*p == (int) nul_char) {
  96                 return build_failed;
  97         }
  98         /* If we are faking it we just return */
  99         if (do_not_exec_rule &&
 100             working_on_targets &&
 101             !call_make &&
 102             !always_exec) {
 103                 return build_ok;
 104         }
 105         /* no_action_was_taken is used to print special message */
 106         no_action_was_taken = false;
 107 
 108         /* Copy string to make it OK to write it. */
 109         q = ALLOC_WC(length + 1);
 110         (void) wscpy(q, p);
 111         /* Write the state file iff this command uses make. */
 112         if (call_make && command_changed) {
 113                 write_state_file(0, false);
 114         }
 115         make_state->stat.time = file_no_time;
 116         (void)exists(make_state);
 117         before = make_state->stat.time;
 118         /*
 119          * Run command directly if it contains no shell meta chars,
 120          * else run it using the shell.
 121          */
 122         if (await(ignore_error,
 123                   silent_error,
 124                   target,
 125                   wcb.get_string(),
 126                   command->meta ?
 127                     doshell(q, ignore_error, redirect_out_err,
 128                             stdout_file, stderr_file, 0) :
 129                     doexec(q, ignore_error, redirect_out_err,
 130                            stdout_file, stderr_file,
 131                            vroot_path, 0),
 132                   send_mtool_msgs,
 133 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
 134                   get_xdrs_ptr(),
 135                   get_job_msg_id()
 136 #else
 137                   NULL,
 138                   -1
 139 #endif
 140                   )) {
 141                 result = build_ok;
 142         } else {
 143                 result = build_failed;
 144         }
 145         retmem(q);
 146 
 147         if ((report_dependencies_level == 0) &&
 148             call_make) {
 149                 make_state->stat.time = file_no_time;
 150                 (void)exists(make_state);
 151                 if (before == make_state->stat.time) {
 152                         return result;
 153                 }
 154                 makefile_type = reading_statefile;
 155                 if (read_trace_level > 1) {
 156                         trace_reader = true;
 157                 }
 158                 temp_file_number++;
 159                 (void) read_simple_file(make_state,
 160                                         false,
 161                                         false,
 162                                         false,
 163                                         false,
 164                                         false,
 165                                         true);
 166                 trace_reader = false;
 167         }
 168         return result;
 169 }