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/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <strings.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <signal.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <wait.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglib.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglocale.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglibmsgs.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#ifndef _STDARG_H
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "stdarg.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#endif
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Private definitions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Maximum number of arguments to pkg_ExecCmdList */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MAX_EXEC_CMD_ARGS 100
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Size of buffer increments when reading from pipe */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define PIPE_BUFFER_INCREMENT 256
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char errfile[L_tmpnam+1];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Public Methods
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandvoid
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandrpterr(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *fp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int c;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errfile[0]) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fp = fopen(errfile, "r")) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((c = getc(fp)) != EOF)
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) putc(c, stderr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(fp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) unlink(errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errfile[0] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandvoid
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandecleanup(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errfile[0]) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) unlink(errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errfile[0] = NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandesystem(char *cmd, int ifd, int ofd)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *perrfile;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland perrfile = tmpnam(NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (perrfile == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkg_gt("unable to create temp error file, errno=%d"),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(errfile, perrfile, sizeof (errfile));
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 if (pid == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this is the child process
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 if (ifd > 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ifd, STDIN_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ofd >= 0 && ofd != STDOUT_FILENO) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) dup2(ofd, STDOUT_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland i = open(errfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (i >= 0) {
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) dup2(i, STDERR_FILENO);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
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
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) execl("/sbin/sh", "/sbin/sh", "-c", cmd, NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt("exec of <%s> failed, errno=%d"), cmd, errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland _exit(99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (pid < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* fork failed! */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(pkg_gt("bad vfork(), errno=%d"), errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this is the parent process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) sighold(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid = waitpid(pid, &status, 0);
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) sigrelse(SIGINT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pid < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1); /* probably interrupted */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland switch (status & 0177) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 0:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 0177:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = status >> 8;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*FALLTHROUGH*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland default:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* terminated by a signal */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = status & 0177;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (status == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ecleanup();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (status);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandFILE *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandepopen(char *cmd, char *mode)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *buffer, *perrfile;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *pp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t alen;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errfile[0]) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* cleanup previous errfile */
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) unlink(errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland perrfile = tmpnam(NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (perrfile == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkg_gt("unable to create temp error file, errno=%d"),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((FILE *)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strlcpy(errfile, perrfile, sizeof (errfile)) > sizeof (errfile)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt("file name max length %d; name is too long: %s"),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland sizeof (errfile), perrfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((FILE *)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = strlen(cmd)+6+strlen(errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland buffer = (char *)calloc(len, sizeof (char));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (buffer == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt("no memory in epopen(), errno=%d"), errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((FILE *)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strchr(cmd, '|')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland alen = snprintf(buffer, len, "(%s) 2>%s", cmd, errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland alen = snprintf(buffer, len, "%s 2>%s", cmd, errfile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (alen > len) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(pkg_gt("command max length %d; cmd is too long: %s"),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len, cmd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((FILE *)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pp = popen(buffer, mode);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free(buffer);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (pp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandepclose(FILE *pp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = pclose(pp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n == 0)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ecleanup();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (n);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: e_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 Waterlande_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 pid_t pid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pid_t resultPid;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int stdinfile = -1;
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 }
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: e_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 Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlande_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 (e_ExecCmdArray(r_status, r_results, a_inputFile,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_cmd, array));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}