/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2015, Joyent, Inc.
*/
/*
* dosys.cc
*
* Execute one commandline
*/
/*
* Included files
*/
#include <alloca.h> /* alloca() */
#include <stdio.h> /* errno */
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <ulimit.h> /* ulimit() */
#include <unistd.h> /* close(), dup2() */
#include <stdlib.h> /* closefrom() */
#include <libintl.h>
/*
* typedefs & structs
*/
/*
* Static variables
*/
/*
* File table of contents
*/
static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path);
/*
* Workaround for NFS bug. Sometimes, when running 'open' on a remote
* dmake server, it fails with "Stale NFS file handle" error.
* The second attempt seems to work.
*/
int
/* Stale NFS file handle. Try again */
}
return res;
}
/*
* void
* redirect_io(char *stdout_file, char *stderr_file)
*
* Redirects stdout and stderr for a child mksh process.
*/
void
{
int i;
(void) closefrom(3);
if ((i = my_open(stdout_file,
} else {
fatal_mksh("*** Error: dup2(3, 1) failed: %s",
}
close(i);
}
if (stderr_file == NULL) {
fatal_mksh("*** Error: dup2(1, 2) failed: %s",
}
} else if ((i = my_open(stderr_file,
} else {
fatal_mksh("*** Error: dup2(3, 2) failed: %s",
}
close(i);
}
}
/*
* doshell(command, ignore_error)
*
* Used to run command lines that include shell meta-characters.
* The make macro SHELL is supposed to contain a path to the shell.
*
* Return value:
* The pid of the process we started
*
* Parameters:
* command The command to run
* ignore_error Should we abort on error?
*
* Global variables used:
* filter_stderr If -X is on we redirect stderr
* shell_name The Name "SHELL", used to get the path to shell
*/
int
doshell(wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, int nice_prio)
{
int argv_index = 0;
int cmd_argv_index;
int length;
register char *shellname;
char *tmp_mbs_buffer;
shell = shell_name;
}
} else {
shellname++;
}
/*
* if the nice priority, nice_prio, is NOT zero (0).
* Nice priorities can be a positive or a negative number.
*/
if (nice_prio != 0) {
}
} else {
}
enable_interrupt((void (*) (int)) SIG_DFL);
#if 0
if (filter_stderr) {
}
#endif
if (nice_prio != 0) {
} else {
}
}
if (childPid == -1) {
}
return childPid;
}
/*
* exec_vp(name, argv, envp, ignore_error)
*
* Like execve, but does path search.
* This starts command when make invokes it directly (without a shell).
*
* Return value:
* Returns false if the exec failed
*
* Parameters:
* name The name of the command to run
* argv Arguments for the command
* envp The environment for it
* ignore_error Should we abort on error?
*
* Global variables used:
* shell_name The Name "SHELL", used to get the path to shell
* vroot_path The path used by the vroot package
*/
static Boolean
exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path)
{
register char *shellname;
shell = shell_name;
}
for (int i = 0; i < 5; i++) {
(void) execve_vroot(name,
argv + 1,
envp,
switch (errno) {
case ENOEXEC:
case ENOENT:
/* That failed. Let the shell handle it */
} else {
shellname++;
}
}
envp,
return failed;
case ETXTBSY:
/*
* The program is busy (debugged?).
* Wait and then try again.
*/
(void) sleep((unsigned) i);
case EAGAIN:
break;
default:
return failed;
}
}
return failed;
}
/*
* doexec(command, ignore_error)
*
* Will scan an argument string and split it into words
* thus building an argument list that can be passed to exec_ve()
*
* Return value:
* The pid of the process started here
*
* Parameters:
* command The command to run
* ignore_error Should we abort on error?
*
* Global variables used:
* filter_stderr If -X is on we redirect stderr
*/
int
doexec(register wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio)
{
char **argv;
int length;
register char **p;
wchar_t *q;
register wchar_t *t;
char *tmp_mbs_buffer;
/*
* if the nice priority, nice_prio, is NOT zero (0).
* Nice priorities can be a positive or a negative number.
*/
if (nice_prio != 0) {
arg_count += 2;
}
if (iswspace(*t)) {
arg_count++;
}
}
/*
* Reserve argv[0] for sh in case of exec_vp failure.
* In fact, doing it may cause the sh command to fail!
*/
p = &argv[1];
} else {
}
if (nice_prio != 0) {
*p++ = strdup(nice_prio_buf);
}
/* Build list of argument words. */
for (t = command; *t;) {
/* This should never happen, right? */
}
q = t;
t++;
}
if (*t) {
}
*p++ = strdup(tmp_mbs_buffer);
} else {
WCSTOMBS(mbs_buffer, q);
*p++ = strdup(mbs_buffer);
}
}
*p = NULL;
/* Then exec the command with that argument list. */
enable_interrupt((void (*) (int)) SIG_DFL);
#if 0
if (filter_stderr) {
}
#endif
}
if (childPid == -1) {
}
}
return childPid;
}
/*
* await(ignore_error, silent_error, target, command, running_pid)
*
* Wait for one child process and analyzes
* the returned status when the child process terminates.
*
* Return value:
* Returns true if commands ran OK
*
* Parameters:
* ignore_error Should we abort on error?
* silent_error Should error messages be suppressed for dmake?
* target The target we are building, for error msgs
* command The command we ran, for error msgs
* running_pid The pid of the process we are waiting for
*
* Static variables used:
* filter_file The fd for the filter file
* filter_file_name The name of the filter file
*
* Global variables used:
* filter_stderr Set if -X is on
*/
await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, void *xdrs_p, int job_msg_id)
{
int status;
char *buffer;
int core_dumped;
int exit_status;
int termination_signal;
if (pid == -1) {
}
}
if (status == 0) {
#ifdef PRINT_EXIT_STATUS
warning_mksh("I'm in await(), and status is 0.");
#endif
return succeeded;
}
#ifdef PRINT_EXIT_STATUS
warning_mksh("I'm in await(), and status is *NOT* 0.");
#endif
#ifdef PRINT_EXIT_STATUS
#endif
/*
* If the child returned an error, we now try to print a
* nice message about it.
*/
if (!silent_error) {
if (exit_status != 0) {
gettext("*** Error code %d"),
} else {
gettext("*** Signal %d"),
if (core_dumped) {
gettext(" - core dumped"));
}
}
if (ignore_error) {
gettext(" (ignored)"));
}
}
#ifdef PRINT_EXIT_STATUS
warning_mksh("I'm in await(), returning failed.");
#endif
return failed;
}
/*
* sh_command2string(command, destination)
*
* Run one sh command and capture the output from it.
*
* Return value:
*
* Parameters:
* command The command to run
* destination Where to deposit the output from the command
*
* Static variables used:
*
* Global variables used:
*/
void
{
register int chr;
int status;
}
if (chr == (int) newline_char) {
chr = (int) space_char;
}
command_generated_output = true;
}
/*
* We don't want to keep the last LINE_FEED since usually
* the output of the 'sh:' command is used to evaluate
* to the output so that the prompt appear in the right place.
* We don't need that
*/
if (command_generated_output){
}
} else {
/*
* If the command didn't generate any output,
* set the buffer to a null string.
*/
}
if (status != 0) {
}
}