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)
  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) wcscpy(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, 
 128                             stdout_file, stderr_file, 0) :
 129                     doexec(q, ignore_error, 
 130                            stdout_file, stderr_file,
 131                            vroot_path, 0),
 132                   NULL,
 133                   -1
 134                   )) {
 135                 result = build_ok;
 136         } else {
 137                 result = build_failed;
 138         }
 139         retmem(q);
 140 
 141         if ((report_dependencies_level == 0) &&
 142             call_make) {
 143                 make_state->stat.time = file_no_time;
 144                 (void)exists(make_state);
 145                 if (before == make_state->stat.time) {
 146                         return result;
 147                 }
 148                 makefile_type = reading_statefile;
 149                 if (read_trace_level > 1) {
 150                         trace_reader = true;
 151                 }
 152                 temp_file_number++;
 153                 (void) read_simple_file(make_state,
 154                                         false,
 155                                         false,
 156                                         false,
 157                                         false,
 158                                         false,
 159                                         true);
 160                 trace_reader = false;
 161         }
 162         return result;
 163 }