5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Module: zones_exec.c
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Group: libinstzones
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Provide "zones" execution interface for install
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * consolidation code
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Public Methods:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * z_ExecCmdArray - Execute a Unix command and return results and status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * _zexec - run a command with arguments on a specified zone
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * _zexec_init_template - used by _zexec to establish contracts
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * _z_zone_exec - Execute a Unix command in a specified zone and return results
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * z_ExecCmdList - Execute a Unix command and return results and status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * System includes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <ctype.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/param.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <strings.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdarg.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <limits.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <signal.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <wait.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stropts.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libintl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <locale.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libcontract.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/contract/process.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/ctfs.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <assert.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * local includes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "instzones_lib.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "zones_strings.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Private structures
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Library Function Prototypes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Local Function Prototypes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * global internal (private) declarations
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *****************************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * global external (public) functions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *****************************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: z_ExecCmdArray
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Synopsis: Execute Unix command and return results
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Execute a Unix command and return results and status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status - [RO, *RW] - (int *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Return (exit) status from Unix command:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == -1 : child terminated with a signal
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != -1 : lower 8-bit value child passed to exit()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_results - [RO, *RW] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Any output generated by the Unix command to stdout
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and to stderr
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL if no output generated
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_inputFile - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing file to be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * used as "standard input" for the command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL to use "/dev/null" as standard input
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_cmd - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing the full path
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the Unix command to execute
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char **a_args - [RO, *RO] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * List of character strings representing the arguments
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to be passed to the Unix command. The list must be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * terminated with an element that is (char *)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - Command executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Look at r_status for results of Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - problems executing command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status and r_results have no meaning;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status will be -1
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_results will be NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: Any results returned is placed in new storage for the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * calling method. The caller must use 'free' to dispose
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the storage once the results are no longer needed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: If 0 is returned, 'r_status' must be queried to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * determine the results of the Unix command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: The system "errno" value from immediately after waitpid() call
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is preserved for the calling method to use to determine
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the system reason why the operation failed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandz_ExecCmdArray(int *r_status, char **r_results,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *a_inputFile, char *a_cmd, char **a_args)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *buffer;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int bufferIndex;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int bufferSize;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int ipipe[2] = {0, 0};
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int stdinfile = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t resultPid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry assertions */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(r_status != NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_cmd != NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(*a_cmd != '\0');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_args != NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset return results buffer pointer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r_results != (char **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_results = (char *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See if command exists
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(a_cmd, F_OK|X_OK) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See if input file exists
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_inputFile != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland stdinfile = open(a_inputFile, O_RDONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland stdinfile = open("/dev/null", O_RDONLY); /* stdin = /dev/null */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stdinfile < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Create a pipe to be used to capture the command output
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pipe(ipipe) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize = PIPE_BUFFER_INCREMENT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferIndex = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland buffer = calloc(1, bufferSize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (buffer == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* flush standard i/o before creating new process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stderr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stdout);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * create new process to execute command in;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfork() is being used to avoid duplicating the parents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * memory space - this means that the child process may
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * not modify any of the parents memory including the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * standard i/o descriptors - all the child can do is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * adjust interrupts and open files as a prelude to a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * call to exec().
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid = vfork();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pid == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forked (child) process ======================
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int i;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset any signals to default */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (i = 0; i < NSIG; i++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigset(i, SIG_DFL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* assign stdin, stdout, stderr as appropriate */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(stdinfile, STDIN_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[0]); /* close out pipe reader side */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ipipe[1], STDOUT_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ipipe[1], STDERR_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Close all open files except standard i/o */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland closefrom(3);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* execute target executable */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) execvp(a_cmd, a_args);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland perror(a_cmd); /* Emit error msg - ends up in callers buffer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _exit(0x00FE);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (pid == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_FORK, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forking (parent) process ====================
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[1]); /* Close write side of pipe */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Spin reading data from the child into the buffer - when the read eofs
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the child has exited
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t bytesRead;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read as much child data as there is available buffer space */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bytesRead = read(ipipe[0], buffer + bufferIndex,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize - bufferIndex);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break out of read loop if end-of-file encountered */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bytesRead == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if error, continue if recoverable, else break out of loop */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bytesRead == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try again: EAGAIN - insufficient resources */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try again: EINTR - interrupted system call */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break out of loop - error not recoverable */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* at least 1 byte read: expand buffer if at end */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferIndex += bytesRead;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bufferIndex >= bufferSize) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland buffer = realloc(buffer,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize += PIPE_BUFFER_INCREMENT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) memset(buffer + bufferIndex, 0,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize - bufferIndex);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[0]); /* Close read side of pipe */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Get subprocess exit status */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland resultPid = waitpid(pid, &status, 0L);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = (resultPid == -1 ? errno : 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break loop if child process status reaped */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (resultPid != -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break loop if not interrupted out of waitpid */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno != EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the child process terminated due to a call to exit(), then
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * set results equal to the 8-bit exit status of the child process;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * otherwise, set the exit status to "-1" indicating that the child
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exited via a signal.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return appropriate output */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!*buffer) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* No contents in output buffer - discard */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (r_results == (char **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Not requested to return results - discard */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* have output and request to return: pass to calling method */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_results = buffer;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (resultPid == -1 ? -1 : 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: _zexec
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: run a command with arguments on a specified zone
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: a_zoneName - pointer to string representing the name of the zone
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to execute the specified command in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_path - pointer to string representing the full path *in the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * non-global zone named by a_zoneName* of the Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to be executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_argv[] - Pointer to array of character strings representing
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the arguments to be passed to the Unix command. The list
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * must be termianted with an element that is (char *)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: a_argv[0] is the "command name" passed to the command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function must be treated like a call to exec()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the exec() is successful, the thread of control is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOT returned, and the process will exit when completed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If this function returns, it means the exec() could not
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * be done, or another fatal error occurred.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland_zexec(const char *a_zoneName, const char *a_path, char *a_argv[])
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland zoneid_t zoneid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland zone_state_t st;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char **new_env = { NULL };
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland priv_set_t *privset;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry assertions */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_zoneName != NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(*a_zoneName != '\0');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_path != NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(*a_path != '\0');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* establish locale settings */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) setlocale(LC_ALL, "");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) textdomain(TEXT_DOMAIN);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* can only be invoked from within the global zone */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (getzoneid() != GLOBAL_ZONEID) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_NOT_IN_GZ, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strcmp(a_zoneName, GLOBAL_ZONENAME) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_GZUSED, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* get the state of the specified zone */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (zone_get_state((char *)a_zoneName, &st) != Z_OK) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_BADZONE, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (st < ZONE_STATE_INSTALLED) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_BADSTATE, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland zone_state_str(st));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (st != ZONE_STATE_RUNNING && st != ZONE_STATE_MOUNTED) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_NOTRUNNING, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland zone_state_str(st));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In both console and non-console cases, we require all privs.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In the console case, because we may need to startup zoneadmd.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In the non-console case in order to do zone_enter(2), zonept()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and other tasks.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Future work: this solution is temporary. Ultimately, we need to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * move to a flexible system which allows the global admin to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * designate that a particular user can zlogin (and probably zlogin
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -C) to a particular zone. This all-root business we have now is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * quite sketchy.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((privset = priv_allocset()) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_PRIV_ALLOCSET, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_GETPPRIV, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland priv_freeset(privset);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (priv_isfullset(privset) == B_FALSE) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_PRIVS, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland priv_freeset(privset);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland priv_freeset(privset);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((zoneid = getzoneidbyname(a_zoneName)) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_NOZONEID, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((new_env = _zexec_prep_env()) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_ASSEMBLE, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In case any of stdin, stdout or stderr are streams,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * anchor them to prevent malicious I_POPs.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Future work: use pipes to entirely eliminate FD leakage
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * into the zone.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ioctl(STDIN_FILENO, I_ANCHOR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ioctl(STDOUT_FILENO, I_ANCHOR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ioctl(STDERR_FILENO, I_ANCHOR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (zone_enter(zoneid) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_ZONEENTER, a_zoneName,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lerrno == EFAULT) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_EFAULT, a_zoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) execve(a_path, &a_argv[0], new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_ZEXEC_EXECFAILURE, a_zoneName, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: _zexec_init_template
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: used by _zexec to establish contracts
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland_zexec_init_template(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int fd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int err = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = open64(CTFS_ROOT "/process/template", O_RDWR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * zlogin doesn't do anything with the contract.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Deliver no events, don't inherit, and allow it to be orphaned.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland err |= ct_tmpl_set_critical(fd, 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland err |= ct_tmpl_set_informative(fd, 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (err || ct_tmpl_activate(fd)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Helper routine for _zexec_prep_env below.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandchar *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland_zexec_add_env(char *name, char *value)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t sz = strlen(name) + strlen(value) + 1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *str;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((str = malloc(sz)) == NULL)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(str, sz, "%s%s", name, value);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (str);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Prepare envp array for exec'd process.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandchar **
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland_zexec_prep_env()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int e = 0, size = 1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char **new_env, *estr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *term = getenv("TERM");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size++; /* for $PATH */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (term != NULL)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In failsafe mode we set $HOME
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In failsafe mode we set $SHELL, since login won't be around to do it.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((new_env = malloc(sizeof (char *) * size)) == NULL)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((estr = _zexec_add_env("PATH=", ZONE_DEF_PATH)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new_env[e++] = estr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (term != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((estr = _zexec_add_env("TERM=", term)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new_env[e++] = estr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((estr = _zexec_add_env("HOME=", "/")) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new_env[e++] = estr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((estr = _zexec_add_env("SHELL=", ZONE_FAILSAFESHELL)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new_env[e++] = estr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new_env[e++] = NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (new_env);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: _z_zone_exec
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Execute a Unix command in a specified zone and return results
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status - [RO, *RW] - (int *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Return (exit) status from Unix command:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == -1 : child terminated with a signal
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != -1 : lower 8-bit value child passed to exit()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_results - [RO, *RW] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Any output generated by the Unix command to stdout
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and to stderr
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL if no output generated
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_inputFile - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing file to be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * used as "standard input" for the command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL to use "/dev/null" as standard input
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_path - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing the full path
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *in the non-global zone named by a_zoneName*of the Unix
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * command to be executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char **a_args - [RO, *RO] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * List of character strings representing the arguments
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to be passed to the Unix command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: The list must be terminated with an element that
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ----- is (char *)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: a_argv[0] is the "command name" passed to the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ----- command executed in the specified non-global zone
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_zoneName - pointer to string representing the name of the zone
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to execute the specified command in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_fds - Pointer to array of integers representing file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * descriptors to remain open during the call - all
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file descriptors above STDERR_FILENO not in this
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * list will be closed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - Command executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Look at r_status for results of Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - problems executing command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status and r_results have no meaning;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status will be -1
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_results will be NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The return (exit) code from the specified Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Special return codes:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -1 : failure to exec process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -2 : could not create contract for greenline
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -3 : fork() failed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -4 : could not open stdin source file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -5 : error from 'waitpid' other than EINTR
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -6 : zones are not supported
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -7 : interrupt received
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: All file descriptores other than 0, 1 and 2 are closed except
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * for those file descriptors listed in the a_fds array.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland_z_zone_exec(int *r_status, char **r_results, char *a_inputFile,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *a_path, char *a_argv[], const char *a_zoneName, int *a_fds)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct sigaction nact;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct sigaction oact;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *buffer;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *thisZoneName;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int bufferIndex;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int bufferSize;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int exit_no;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int ipipe[2] = {0, 0};
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int stdinfile = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int tmpl_fd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t child_pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t result_pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland void (*funcSighup)();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland void (*funcSigint)();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry assertions */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_path != (char *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(*a_path != '\0');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_argv != (char **)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_argv[0] != (char *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(*a_argv[0] != '\0');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland assert(a_zoneName != (char *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if requested to execute in current zone name, directly execute
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland thisZoneName = z_get_zonename();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = (strcmp(a_zoneName, thisZoneName) == 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* entry debugging info */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_echoDebug(DBG_ZONE_EXEC_CMD_ENTER, a_path, a_zoneName, thisZoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(thisZoneName);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (n = 0; a_argv[n]; n++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_echoDebug(DBG_ARG, n, a_argv[n]);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if this zone, just exec the command directly */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (status != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (z_ExecCmdArray(r_status, r_results, a_inputFile,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_path, a_argv));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset return results buffer pointer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r_results != (char **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_results = (char *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = -1; /* -1 : failure to exec process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if zones are not implemented, return TRUE */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!z_zones_are_implemented()) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-6); /* -6 : zones are not supported */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((tmpl_fd = _zexec_init_template()) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-2); /* -2 : cannot create greenline contract */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See if input file exists
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_inputFile != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland stdinfile = open(a_inputFile, O_RDONLY);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland stdinfile = open("/dev/null", O_RDONLY); /* stdin = /dev/null */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stdinfile < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-4); /* -4 : could not open stdin source file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Create a pipe to be used to capture the command output
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pipe(ipipe) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize = PIPE_BUFFER_INCREMENT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferIndex = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland buffer = calloc(1, bufferSize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (buffer == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* flush standard i/o before creating new process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stderr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fflush(stdout);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * hold SIGINT/SIGHUP signals and reset signal received counter;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * after the fork1() the parent and child need to setup their respective
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * interrupt handling and release the hold on the signals
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sighold(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sighold(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_global_data._z_SigReceived = 0; /* no signals received */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fork off a new process to execute command in;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fork1() is used instead of vfork() so the child process can
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * perform operations that would modify the parent process if
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfork() were used
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland child_pid = fork1();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (child_pid < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fork failed!
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ct_tmpl_clear(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_program_error(ERR_FORK, strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-3); /* -3 : fork() failed */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (child_pid == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int i;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forked (child) process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ct_tmpl_clear(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset any signals to default */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (i = 0; i < NSIG; i++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigset(i, SIG_DFL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* assign stdin, stdout, stderr as appropriate */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(stdinfile, STDIN_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[0]); /* close out pipe reader side */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ipipe[1], STDOUT_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ipipe[1], STDERR_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * close all file descriptors not in the a_fds list
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release all held signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* execute command in the specified non-global zone */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _exit(_zexec(a_zoneName, a_path, a_argv));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *********************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the forking (parent) process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *********************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* register child process i.d. so signal handlers can pass signal on */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_global_data._z_ChildProcessId = child_pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * setup signal handlers for SIGINT and SIGHUP and release hold
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* hook SIGINT to _z_sig_trap() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = _z_sig_trap;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sigaction(SIGINT, &nact, &oact) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSigint = SIG_DFL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSigint = oact.sa_handler;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* hook SIGHUP to _z_sig_trap() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = _z_sig_trap;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sigaction(SIGHUP, &nact, &oact) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSighup = SIG_DFL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland funcSighup = oact.sa_handler;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release hold on signals */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGHUP);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ct_tmpl_clear(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(tmpl_fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(stdinfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[1]); /* Close write side of pipe */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Spin reading data from the child into the buffer - when the read eofs
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the child has exited
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t bytesRead;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read as much child data as there is available buffer space */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bytesRead = read(ipipe[0], buffer + bufferIndex,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize - bufferIndex);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break out of read loop if end-of-file encountered */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bytesRead == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if error, continue if recoverable, else break out of loop */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bytesRead == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try again: EAGAIN - insufficient resources */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try again: EINTR - interrupted system call */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break out of loop - error not recoverable */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* at least 1 byte read: expand buffer if at end */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferIndex += bytesRead;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (bufferIndex >= bufferSize) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland buffer = realloc(buffer,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize += PIPE_BUFFER_INCREMENT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) memset(buffer + bufferIndex, 0,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bufferSize - bufferIndex);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(ipipe[0]); /* Close read side of pipe */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * wait for the process to exit, reap child exit status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland result_pid = waitpid(child_pid, &status, 0L);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = (result_pid == -1 ? errno : 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break loop if child process status reaped */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (result_pid != -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break loop if not interrupted out of waitpid */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno != EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset child process i.d. so signal handlers do not pass signals on */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _z_global_data._z_ChildProcessId = -1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the child process terminated due to a call to exit(), then
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * set results equal to the 8-bit exit status of the child process;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * otherwise, set the exit status to "-1" indicating that the child
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exited via a signal.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (WIFEXITED(status)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = WEXITSTATUS(status);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((_z_global_data._z_SigReceived != 0) && (*r_status == 0)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = 1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_status = -1; /* -1 : failure to exec process */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* determine proper exit code */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (result_pid == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = -5; /* -5 : error from 'waitpid' other than EINTR */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (_z_global_data._z_SigReceived != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = -7; /* -7 : interrupt received */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit_no = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return appropriate output */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!*buffer) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* No contents in output buffer - discard */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (r_results == (char **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Not requested to return results - discard */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* have output and request to return: pass to calling method */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_results = buffer;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * reset signal handlers
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset SIGINT */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = funcSigint;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset SIGHUP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_handler = funcSighup;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nact.sa_flags = SA_RESTART;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigemptyset(&nact.sa_mask);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if signal received during command execution, interrupt
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this process now.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (_z_global_data._z_SigReceived != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) kill(getpid(), SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set errno and return */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (exit_no);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: z_ExecCmdList
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Synopsis: Execute Unix command and return results
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Execute a Unix command and return results and status
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status - [RO, *RW] - (int *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Return (exit) status from Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_results - [RO, *RW] - (char **)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Any output generated by the Unix command to stdout
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and to stderr
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL if no output generated
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_inputFile - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing file to be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * used as "standard input" for the command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL to use "/dev/null" as standard input
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_cmd - [RO, *RO] - (char *)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to character string representing the full path
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the Unix command to execute
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ... - [RO] (?)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Zero or more arguments to the Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The argument list must be ended with (void *)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - Command executed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Look at r_status for results of Unix command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - problems executing command
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * r_status and r_results have no meaning
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: Any results returned is placed in new storage for the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * calling method. The caller must use 'free' to dispose
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the storage once the results are no longer needed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: If LU_SUCCESS is returned, 'r_status' must be queried to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * determine the results of the Unix command.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*VARARGS*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandz_ExecCmdList(int *r_status, char **r_results,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *a_inputFile, char *a_cmd, ...)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland va_list ap; /* references variable argument list */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *array[MAX_EXEC_CMD_ARGS+1];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int argno = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Create argument array for exec system call
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bzero(array, sizeof (array));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland va_start(ap, a_cmd); /* Begin variable argument processing */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (argno = 0; argno < MAX_EXEC_CMD_ARGS; argno++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland array[argno] = va_arg(ap, char *);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (array[argno] == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland va_end(ap);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (z_ExecCmdArray(r_status, r_results, a_inputFile,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_cmd, array));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}