1 /*
2  * CDDL HEADER START
3  *
4  * This file and its contents are supplied under the terms of the
5  * Common Development and Distribution License ("CDDL"), version 1.0.
6  * You may use this file only in accordance with the terms of version
7  * 1.0 of the CDDL.
8  *
9  * A full copy of the text of the CDDL should have accompanied this
10  * source.  A copy of the CDDL is also available via the Internet at
11  * http://www.opensource.org/licenses/cddl1.txt
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 /*
24  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25  * Use is subject to license terms.
26  */
27 /*
28  * @(#)dosys.cc 1.45 06/12/12
29  */
30 
31 #pragma	ident	"@(#)dosys.cc	1.45	06/12/12"
32 
33 /*
34  * Copyright 2017-2018 J. Schilling
35  *
36  * @(#)dosys.cc	1.5 21/08/15 2017-2018 J. Schilling
37  */
38 #include <schily/mconfig.h>
39 #ifndef lint
40 static	UConst char sccsid[] =
41 	"@(#)dosys.cc	1.5 21/08/15 2017-2018 J. Schilling";
42 #endif
43 
44 /*
45  *	dosys.cc
46  *
47  *	Execute one commandline
48  */
49 
50 /*
51  * Included files
52  */
53 #include <mk/defs.h>
54 #include <mksh/dosys.h>		/* doshell(), doexec() */
55 #include <mksh/misc.h>		/* getmem() */
56 
57 /*
58  * Defined macros
59  */
60 
61 /*
62  * typedefs & structs
63  */
64 
65 /*
66  * Static variables
67  */
68 static	int		filter_file;
69 static	char		*filter_file_name;
70 
71 /*
72  * File table of contents
73  */
74 static	void		redirect_stderr(void);
75 
76 /*
77  *	dosys(command, ignore_error, call_make, silent_error, target)
78  *
79  *	Check if command string contains meta chars and dispatch to
80  *	the proper routine for executing one command line.
81  *
82  *	Return value:
83  *				Indicates if the command execution failed
84  *
85  *	Parameters:
86  *		command		The command to run
87  *		ignore_error	Should make abort when an error is seen?
88  *		call_make	Did command reference $(MAKE) ?
89  *		silent_error	Should error messages be suppressed for pmake?
90  *		target		Target we are building
91  *
92  *	Global variables used:
93  *		do_not_exec_rule Is -n on?
94  *		working_on_targets We started processing real targets
95  */
96 Doname
dosys(register Name command,register Boolean ignore_error,register Boolean call_make,Boolean silent_error,Boolean always_exec,Name target,Boolean redirect_out_err)97 dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err)
98 {
99 	timestruc_t		before;
100 	register int		length = command->hash.length;
101 	Wstring			wcb(command);
102 	register wchar_t	*p = wcb.get_string();
103 	register wchar_t	*q;
104 	Doname			result;
105 
106 	/* Strip spaces from head of command string */
107 	while (iswspace(*p)) {
108 		p++, length--;
109 	}
110 	if (*p == (int) nul_char) {
111 		return build_failed;
112 	}
113 	/* If we are faking it we just return */
114 	if (do_not_exec_rule &&
115 	    working_on_targets &&
116 	    !call_make &&
117 	    !always_exec) {
118 		return build_ok;
119 	}
120 	/* no_action_was_taken is used to print special message */
121 	no_action_was_taken = false;
122 
123 	/* Copy string to make it OK to write it. */
124 	q = ALLOC_WC(length + 1);
125 	(void) wcscpy(q, p);
126 	/* Write the state file iff this command uses make. */
127 	if (call_make && command_changed) {
128 		write_state_file(0, false);
129 	}
130 	make_state->stat.time = file_no_time;
131 	(void)exists(make_state);
132 	before = make_state->stat.time;
133 	/*
134 	 * Run command directly if it contains no shell meta chars,
135 	 * else run it using the shell.
136 	 */
137 	if (await(ignore_error,
138 		  silent_error,
139 		  target,
140 		  wcb.get_string(),
141                   command->meta ?
142 	            doshell(q, ignore_error, redirect_out_err,
143 			    stdout_file, stderr_file, 0) :
144 	            doexec(q, ignore_error, redirect_out_err,
145 		 	   stdout_file, stderr_file,
146 	                   vroot_path, 0),
147 	          send_mtool_msgs,
148 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
149                   get_xdrs_ptr(),
150                   get_job_msg_id()
151 #else
152                   NULL,
153                   -1
154 #endif
155 	          )) {
156 		result = build_ok;
157 	} else {
158 		result = build_failed;
159 	}
160 	retmem(q);
161 
162 	if ((report_dependencies_level == 0) &&
163 	    call_make) {
164 		make_state->stat.time = file_no_time;
165 		(void)exists(make_state);
166 		if (before == make_state->stat.time) {
167 			return result;
168 		}
169 		makefile_type = reading_statefile;
170 		if (read_trace_level > 1) {
171 			trace_reader = true;
172 		}
173 		temp_file_number++;
174 		(void) read_simple_file(make_state,
175 					false,
176 					false,
177 					false,
178 					false,
179 					false,
180 					true);
181 		trace_reader = false;
182 	}
183 	return result;
184 }
185