15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland * CDDL HEADER START
35c51f124SMoriah Waterland *
45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland *
85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland * See the License for the specific language governing permissions
115c51f124SMoriah Waterland * and limitations under the License.
125c51f124SMoriah Waterland *
135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland *
195c51f124SMoriah Waterland * CDDL HEADER END
205c51f124SMoriah Waterland */
215c51f124SMoriah Waterland
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
245c51f124SMoriah Waterland * Use is subject to license terms.
255c51f124SMoriah Waterland */
265c51f124SMoriah Waterland
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland
305c51f124SMoriah Waterland
315c51f124SMoriah Waterland
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <errno.h>
345c51f124SMoriah Waterland #include <string.h>
355c51f124SMoriah Waterland #include <strings.h>
365c51f124SMoriah Waterland #include <signal.h>
375c51f124SMoriah Waterland #include <fcntl.h>
385c51f124SMoriah Waterland #include <stdlib.h>
395c51f124SMoriah Waterland #include <unistd.h>
405c51f124SMoriah Waterland #include <wait.h>
415c51f124SMoriah Waterland #include <sys/types.h>
425c51f124SMoriah Waterland #include "pkglib.h"
435c51f124SMoriah Waterland #include "pkglocale.h"
445c51f124SMoriah Waterland #include "pkglibmsgs.h"
455c51f124SMoriah Waterland
465c51f124SMoriah Waterland #ifndef _STDARG_H
475c51f124SMoriah Waterland #include "stdarg.h"
485c51f124SMoriah Waterland #endif
495c51f124SMoriah Waterland
505c51f124SMoriah Waterland /*
515c51f124SMoriah Waterland * Private definitions
525c51f124SMoriah Waterland */
535c51f124SMoriah Waterland
545c51f124SMoriah Waterland /* Maximum number of arguments to pkg_ExecCmdList */
555c51f124SMoriah Waterland
565c51f124SMoriah Waterland #define MAX_EXEC_CMD_ARGS 100
575c51f124SMoriah Waterland
585c51f124SMoriah Waterland /* Size of buffer increments when reading from pipe */
595c51f124SMoriah Waterland
605c51f124SMoriah Waterland #define PIPE_BUFFER_INCREMENT 256
615c51f124SMoriah Waterland
625c51f124SMoriah Waterland static char errfile[L_tmpnam+1];
635c51f124SMoriah Waterland
645c51f124SMoriah Waterland /*
655c51f124SMoriah Waterland * Public Methods
665c51f124SMoriah Waterland */
675c51f124SMoriah Waterland
685c51f124SMoriah Waterland
695c51f124SMoriah Waterland void
rpterr(void)705c51f124SMoriah Waterland rpterr(void)
715c51f124SMoriah Waterland {
725c51f124SMoriah Waterland FILE *fp;
735c51f124SMoriah Waterland int c;
745c51f124SMoriah Waterland
755c51f124SMoriah Waterland if (errfile[0]) {
765c51f124SMoriah Waterland if (fp = fopen(errfile, "r")) {
775c51f124SMoriah Waterland while ((c = getc(fp)) != EOF)
78*4656d474SGarrett D'Amore (void) putc(c, stderr);
795c51f124SMoriah Waterland (void) fclose(fp);
805c51f124SMoriah Waterland }
815c51f124SMoriah Waterland (void) unlink(errfile);
825c51f124SMoriah Waterland errfile[0] = '\0';
835c51f124SMoriah Waterland }
845c51f124SMoriah Waterland }
855c51f124SMoriah Waterland
865c51f124SMoriah Waterland void
ecleanup(void)875c51f124SMoriah Waterland ecleanup(void)
885c51f124SMoriah Waterland {
895c51f124SMoriah Waterland if (errfile[0]) {
905c51f124SMoriah Waterland (void) unlink(errfile);
915c51f124SMoriah Waterland errfile[0] = NULL;
925c51f124SMoriah Waterland }
935c51f124SMoriah Waterland }
945c51f124SMoriah Waterland
955c51f124SMoriah Waterland int
esystem(char * cmd,int ifd,int ofd)965c51f124SMoriah Waterland esystem(char *cmd, int ifd, int ofd)
975c51f124SMoriah Waterland {
985c51f124SMoriah Waterland char *perrfile;
995c51f124SMoriah Waterland int status = 0;
1005c51f124SMoriah Waterland pid_t pid;
1015c51f124SMoriah Waterland
1025c51f124SMoriah Waterland perrfile = tmpnam(NULL);
1035c51f124SMoriah Waterland if (perrfile == NULL) {
1045c51f124SMoriah Waterland progerr(
1055c51f124SMoriah Waterland pkg_gt("unable to create temp error file, errno=%d"),
1065c51f124SMoriah Waterland errno);
1075c51f124SMoriah Waterland return (-1);
1085c51f124SMoriah Waterland }
1095c51f124SMoriah Waterland (void) strlcpy(errfile, perrfile, sizeof (errfile));
1105c51f124SMoriah Waterland
1115c51f124SMoriah Waterland /* flush standard i/o before creating new process */
1125c51f124SMoriah Waterland
1135c51f124SMoriah Waterland (void) fflush(stderr);
1145c51f124SMoriah Waterland (void) fflush(stdout);
1155c51f124SMoriah Waterland
1165c51f124SMoriah Waterland /*
1175c51f124SMoriah Waterland * create new process to execute command in;
1185c51f124SMoriah Waterland * vfork() is being used to avoid duplicating the parents
1195c51f124SMoriah Waterland * memory space - this means that the child process may
1205c51f124SMoriah Waterland * not modify any of the parents memory including the
1215c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is
1225c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a
1235c51f124SMoriah Waterland * call to exec().
1245c51f124SMoriah Waterland */
1255c51f124SMoriah Waterland
1265c51f124SMoriah Waterland pid = vfork();
1275c51f124SMoriah Waterland if (pid == 0) {
1285c51f124SMoriah Waterland /*
1295c51f124SMoriah Waterland * this is the child process
1305c51f124SMoriah Waterland */
1315c51f124SMoriah Waterland int i;
1325c51f124SMoriah Waterland
1335c51f124SMoriah Waterland /* reset any signals to default */
1345c51f124SMoriah Waterland
1355c51f124SMoriah Waterland for (i = 0; i < NSIG; i++) {
1365c51f124SMoriah Waterland (void) sigset(i, SIG_DFL);
1375c51f124SMoriah Waterland }
1385c51f124SMoriah Waterland
1395c51f124SMoriah Waterland if (ifd > 0) {
1405c51f124SMoriah Waterland (void) dup2(ifd, STDIN_FILENO);
1415c51f124SMoriah Waterland }
1425c51f124SMoriah Waterland
1435c51f124SMoriah Waterland if (ofd >= 0 && ofd != STDOUT_FILENO) {
1445c51f124SMoriah Waterland (void) dup2(ofd, STDOUT_FILENO);
1455c51f124SMoriah Waterland }
1465c51f124SMoriah Waterland
1475c51f124SMoriah Waterland i = open(errfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
1485c51f124SMoriah Waterland if (i >= 0) {
149*4656d474SGarrett D'Amore (void) dup2(i, STDERR_FILENO);
1505c51f124SMoriah Waterland }
1515c51f124SMoriah Waterland
1525c51f124SMoriah Waterland /* Close all open files except standard i/o */
1535c51f124SMoriah Waterland
1545c51f124SMoriah Waterland closefrom(3);
1555c51f124SMoriah Waterland
1565c51f124SMoriah Waterland /* execute target executable */
1575c51f124SMoriah Waterland
158*4656d474SGarrett D'Amore (void) execl("/sbin/sh", "/sbin/sh", "-c", cmd, NULL);
1595c51f124SMoriah Waterland progerr(pkg_gt("exec of <%s> failed, errno=%d"), cmd, errno);
1605c51f124SMoriah Waterland _exit(99);
1615c51f124SMoriah Waterland } else if (pid < 0) {
1625c51f124SMoriah Waterland /* fork failed! */
1635c51f124SMoriah Waterland
1645c51f124SMoriah Waterland logerr(pkg_gt("bad vfork(), errno=%d"), errno);
1655c51f124SMoriah Waterland return (-1);
1665c51f124SMoriah Waterland }
1675c51f124SMoriah Waterland
1685c51f124SMoriah Waterland /*
1695c51f124SMoriah Waterland * this is the parent process
1705c51f124SMoriah Waterland */
1715c51f124SMoriah Waterland
172*4656d474SGarrett D'Amore (void) sighold(SIGINT);
1735c51f124SMoriah Waterland pid = waitpid(pid, &status, 0);
174*4656d474SGarrett D'Amore (void) sigrelse(SIGINT);
1755c51f124SMoriah Waterland
1765c51f124SMoriah Waterland if (pid < 0) {
1775c51f124SMoriah Waterland return (-1); /* probably interrupted */
1785c51f124SMoriah Waterland }
1795c51f124SMoriah Waterland
1805c51f124SMoriah Waterland switch (status & 0177) {
1815c51f124SMoriah Waterland case 0:
1825c51f124SMoriah Waterland case 0177:
1835c51f124SMoriah Waterland status = status >> 8;
1845c51f124SMoriah Waterland /*FALLTHROUGH*/
1855c51f124SMoriah Waterland
1865c51f124SMoriah Waterland default:
1875c51f124SMoriah Waterland /* terminated by a signal */
1885c51f124SMoriah Waterland status = status & 0177;
1895c51f124SMoriah Waterland }
1905c51f124SMoriah Waterland
1915c51f124SMoriah Waterland if (status == 0) {
1925c51f124SMoriah Waterland ecleanup();
1935c51f124SMoriah Waterland }
1945c51f124SMoriah Waterland
1955c51f124SMoriah Waterland return (status);
1965c51f124SMoriah Waterland }
1975c51f124SMoriah Waterland
1985c51f124SMoriah Waterland FILE *
epopen(char * cmd,char * mode)1995c51f124SMoriah Waterland epopen(char *cmd, char *mode)
2005c51f124SMoriah Waterland {
2015c51f124SMoriah Waterland char *buffer, *perrfile;
2025c51f124SMoriah Waterland FILE *pp;
2035c51f124SMoriah Waterland size_t len;
2045c51f124SMoriah Waterland size_t alen;
2055c51f124SMoriah Waterland
2065c51f124SMoriah Waterland if (errfile[0]) {
2075c51f124SMoriah Waterland /* cleanup previous errfile */
208*4656d474SGarrett D'Amore (void) unlink(errfile);
2095c51f124SMoriah Waterland }
2105c51f124SMoriah Waterland
2115c51f124SMoriah Waterland perrfile = tmpnam(NULL);
2125c51f124SMoriah Waterland if (perrfile == NULL) {
2135c51f124SMoriah Waterland progerr(
2145c51f124SMoriah Waterland pkg_gt("unable to create temp error file, errno=%d"),
2155c51f124SMoriah Waterland errno);
2165c51f124SMoriah Waterland return ((FILE *)0);
2175c51f124SMoriah Waterland }
2185c51f124SMoriah Waterland
2195c51f124SMoriah Waterland if (strlcpy(errfile, perrfile, sizeof (errfile)) > sizeof (errfile)) {
2205c51f124SMoriah Waterland progerr(pkg_gt("file name max length %d; name is too long: %s"),
2215c51f124SMoriah Waterland sizeof (errfile), perrfile);
2225c51f124SMoriah Waterland return ((FILE *)0);
2235c51f124SMoriah Waterland }
2245c51f124SMoriah Waterland
2255c51f124SMoriah Waterland len = strlen(cmd)+6+strlen(errfile);
2265c51f124SMoriah Waterland buffer = (char *)calloc(len, sizeof (char));
2275c51f124SMoriah Waterland if (buffer == NULL) {
2285c51f124SMoriah Waterland progerr(pkg_gt("no memory in epopen(), errno=%d"), errno);
2295c51f124SMoriah Waterland return ((FILE *)0);
2305c51f124SMoriah Waterland }
2315c51f124SMoriah Waterland
2325c51f124SMoriah Waterland if (strchr(cmd, '|')) {
2335c51f124SMoriah Waterland alen = snprintf(buffer, len, "(%s) 2>%s", cmd, errfile);
2345c51f124SMoriah Waterland } else {
2355c51f124SMoriah Waterland alen = snprintf(buffer, len, "%s 2>%s", cmd, errfile);
2365c51f124SMoriah Waterland }
2375c51f124SMoriah Waterland
2385c51f124SMoriah Waterland if (alen > len) {
2395c51f124SMoriah Waterland progerr(pkg_gt("command max length %d; cmd is too long: %s"),
2405c51f124SMoriah Waterland len, cmd);
2415c51f124SMoriah Waterland return ((FILE *)0);
2425c51f124SMoriah Waterland }
2435c51f124SMoriah Waterland
2445c51f124SMoriah Waterland pp = popen(buffer, mode);
2455c51f124SMoriah Waterland
2465c51f124SMoriah Waterland free(buffer);
2475c51f124SMoriah Waterland return (pp);
2485c51f124SMoriah Waterland }
2495c51f124SMoriah Waterland
2505c51f124SMoriah Waterland int
epclose(FILE * pp)2515c51f124SMoriah Waterland epclose(FILE *pp)
2525c51f124SMoriah Waterland {
2535c51f124SMoriah Waterland int n;
2545c51f124SMoriah Waterland
2555c51f124SMoriah Waterland n = pclose(pp);
2565c51f124SMoriah Waterland if (n == 0)
2575c51f124SMoriah Waterland ecleanup();
2585c51f124SMoriah Waterland return (n);
2595c51f124SMoriah Waterland }
2605c51f124SMoriah Waterland
2615c51f124SMoriah Waterland /*
2625c51f124SMoriah Waterland * Name: e_ExecCmdArray
2635c51f124SMoriah Waterland * Synopsis: Execute Unix command and return results
2645c51f124SMoriah Waterland * Description: Execute a Unix command and return results and status
2655c51f124SMoriah Waterland * Arguments:
2665c51f124SMoriah Waterland * r_status - [RO, *RW] - (int *)
2675c51f124SMoriah Waterland * Return (exit) status from Unix command:
2685c51f124SMoriah Waterland * == -1 : child terminated with a signal
2695c51f124SMoriah Waterland * != -1 : lower 8-bit value child passed to exit()
2705c51f124SMoriah Waterland * r_results - [RO, *RW] - (char **)
2715c51f124SMoriah Waterland * Any output generated by the Unix command to stdout
2725c51f124SMoriah Waterland * and to stderr
2735c51f124SMoriah Waterland * == (char *)NULL if no output generated
2745c51f124SMoriah Waterland * a_inputFile - [RO, *RO] - (char *)
2755c51f124SMoriah Waterland * Pointer to character string representing file to be
2765c51f124SMoriah Waterland * used as "standard input" for the command.
2775c51f124SMoriah Waterland * == (char *)NULL to use "/dev/null" as standard input
2785c51f124SMoriah Waterland * a_cmd - [RO, *RO] - (char *)
2795c51f124SMoriah Waterland * Pointer to character string representing the full path
2805c51f124SMoriah Waterland * of the Unix command to execute
2815c51f124SMoriah Waterland * char **a_args - [RO, *RO] - (char **)
2825c51f124SMoriah Waterland * List of character strings representing the arguments
2835c51f124SMoriah Waterland * to be passed to the Unix command. The list must be
2845c51f124SMoriah Waterland * terminated with an element that is (char *)NULL
2855c51f124SMoriah Waterland * Returns: int
2865c51f124SMoriah Waterland * == 0 - Command executed
2875c51f124SMoriah Waterland * Look at r_status for results of Unix command
2885c51f124SMoriah Waterland * != 0 - problems executing command
2895c51f124SMoriah Waterland * r_status and r_results have no meaning;
2905c51f124SMoriah Waterland * r_status will be -1
2915c51f124SMoriah Waterland * r_results will be NULL
2925c51f124SMoriah Waterland * NOTE: Any results returned is placed in new storage for the
2935c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
2945c51f124SMoriah Waterland * of the storage once the results are no longer needed.
2955c51f124SMoriah Waterland * NOTE: If 0 is returned, 'r_status' must be queried to
2965c51f124SMoriah Waterland * determine the results of the Unix command.
2975c51f124SMoriah Waterland * NOTE: The system "errno" value from immediately after waitpid() call
2985c51f124SMoriah Waterland * is preserved for the calling method to use to determine
2995c51f124SMoriah Waterland * the system reason why the operation failed.
3005c51f124SMoriah Waterland */
3015c51f124SMoriah Waterland
3025c51f124SMoriah Waterland int
e_ExecCmdArray(int * r_status,char ** r_results,char * a_inputFile,char * a_cmd,char ** a_args)3035c51f124SMoriah Waterland e_ExecCmdArray(int *r_status, char **r_results,
3045c51f124SMoriah Waterland char *a_inputFile, char *a_cmd, char **a_args)
3055c51f124SMoriah Waterland {
3065c51f124SMoriah Waterland char *buffer;
3075c51f124SMoriah Waterland int bufferIndex;
3085c51f124SMoriah Waterland int bufferSize;
3095c51f124SMoriah Waterland int ipipe[2] = {0, 0};
3105c51f124SMoriah Waterland pid_t pid;
3115c51f124SMoriah Waterland pid_t resultPid;
3125c51f124SMoriah Waterland int status;
3135c51f124SMoriah Waterland int lerrno;
3145c51f124SMoriah Waterland int stdinfile = -1;
3155c51f124SMoriah Waterland
3165c51f124SMoriah Waterland /* reset return results buffer pointer */
3175c51f124SMoriah Waterland
3185c51f124SMoriah Waterland if (r_results != (char **)NULL) {
3195c51f124SMoriah Waterland *r_results = (char *)NULL;
3205c51f124SMoriah Waterland }
3215c51f124SMoriah Waterland
3225c51f124SMoriah Waterland *r_status = -1;
3235c51f124SMoriah Waterland
3245c51f124SMoriah Waterland /*
3255c51f124SMoriah Waterland * See if command exists
3265c51f124SMoriah Waterland */
3275c51f124SMoriah Waterland
3285c51f124SMoriah Waterland if (access(a_cmd, F_OK|X_OK) != 0) {
3295c51f124SMoriah Waterland return (-1);
3305c51f124SMoriah Waterland }
3315c51f124SMoriah Waterland
3325c51f124SMoriah Waterland /*
3335c51f124SMoriah Waterland * See if input file exists
3345c51f124SMoriah Waterland */
3355c51f124SMoriah Waterland
3365c51f124SMoriah Waterland if (a_inputFile != (char *)NULL) {
3375c51f124SMoriah Waterland stdinfile = open(a_inputFile, O_RDONLY);
3385c51f124SMoriah Waterland } else {
3395c51f124SMoriah Waterland stdinfile = open("/dev/null", O_RDONLY); /* stdin = /dev/null */
3405c51f124SMoriah Waterland }
3415c51f124SMoriah Waterland
3425c51f124SMoriah Waterland if (stdinfile < 0) {
3435c51f124SMoriah Waterland return (-1);
3445c51f124SMoriah Waterland }
3455c51f124SMoriah Waterland
3465c51f124SMoriah Waterland /*
3475c51f124SMoriah Waterland * Create a pipe to be used to capture the command output
3485c51f124SMoriah Waterland */
3495c51f124SMoriah Waterland
3505c51f124SMoriah Waterland if (pipe(ipipe) != 0) {
3515c51f124SMoriah Waterland (void) close(stdinfile);
3525c51f124SMoriah Waterland return (-1);
3535c51f124SMoriah Waterland }
3545c51f124SMoriah Waterland
3555c51f124SMoriah Waterland
3565c51f124SMoriah Waterland bufferSize = PIPE_BUFFER_INCREMENT;
3575c51f124SMoriah Waterland bufferIndex = 0;
3585c51f124SMoriah Waterland buffer = calloc(1, bufferSize);
3595c51f124SMoriah Waterland if (buffer == (char *)NULL) {
3605c51f124SMoriah Waterland (void) close(stdinfile);
3615c51f124SMoriah Waterland return (-1);
3625c51f124SMoriah Waterland }
3635c51f124SMoriah Waterland
3645c51f124SMoriah Waterland /* flush standard i/o before creating new process */
3655c51f124SMoriah Waterland
3665c51f124SMoriah Waterland (void) fflush(stderr);
3675c51f124SMoriah Waterland (void) fflush(stdout);
3685c51f124SMoriah Waterland
3695c51f124SMoriah Waterland /*
3705c51f124SMoriah Waterland * create new process to execute command in;
3715c51f124SMoriah Waterland * vfork() is being used to avoid duplicating the parents
3725c51f124SMoriah Waterland * memory space - this means that the child process may
3735c51f124SMoriah Waterland * not modify any of the parents memory including the
3745c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is
3755c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a
3765c51f124SMoriah Waterland * call to exec().
3775c51f124SMoriah Waterland */
3785c51f124SMoriah Waterland
3795c51f124SMoriah Waterland pid = vfork();
3805c51f124SMoriah Waterland
3815c51f124SMoriah Waterland if (pid == 0) {
3825c51f124SMoriah Waterland /*
3835c51f124SMoriah Waterland * This is the forked (child) process ======================
3845c51f124SMoriah Waterland */
3855c51f124SMoriah Waterland
3865c51f124SMoriah Waterland int i;
3875c51f124SMoriah Waterland
3885c51f124SMoriah Waterland /* reset any signals to default */
3895c51f124SMoriah Waterland
3905c51f124SMoriah Waterland for (i = 0; i < NSIG; i++) {
3915c51f124SMoriah Waterland (void) sigset(i, SIG_DFL);
3925c51f124SMoriah Waterland }
3935c51f124SMoriah Waterland
3945c51f124SMoriah Waterland /* assign stdin, stdout, stderr as appropriate */
3955c51f124SMoriah Waterland
3965c51f124SMoriah Waterland (void) dup2(stdinfile, STDIN_FILENO);
3975c51f124SMoriah Waterland (void) close(ipipe[0]); /* close out pipe reader side */
3985c51f124SMoriah Waterland (void) dup2(ipipe[1], STDOUT_FILENO);
3995c51f124SMoriah Waterland (void) dup2(ipipe[1], STDERR_FILENO);
4005c51f124SMoriah Waterland
4015c51f124SMoriah Waterland /* Close all open files except standard i/o */
4025c51f124SMoriah Waterland
4035c51f124SMoriah Waterland closefrom(3);
4045c51f124SMoriah Waterland
4055c51f124SMoriah Waterland /* execute target executable */
4065c51f124SMoriah Waterland
4075c51f124SMoriah Waterland (void) execvp(a_cmd, a_args);
4085c51f124SMoriah Waterland perror(a_cmd); /* Emit error msg - ends up in callers buffer */
4095c51f124SMoriah Waterland _exit(0x00FE);
4105c51f124SMoriah Waterland }
4115c51f124SMoriah Waterland
4125c51f124SMoriah Waterland /*
4135c51f124SMoriah Waterland * This is the forking (parent) process ====================
4145c51f124SMoriah Waterland */
4155c51f124SMoriah Waterland
4165c51f124SMoriah Waterland (void) close(stdinfile);
4175c51f124SMoriah Waterland (void) close(ipipe[1]); /* Close write side of pipe */
4185c51f124SMoriah Waterland
4195c51f124SMoriah Waterland /*
4205c51f124SMoriah Waterland * Spin reading data from the child into the buffer - when the read eofs
4215c51f124SMoriah Waterland * the child has exited
4225c51f124SMoriah Waterland */
4235c51f124SMoriah Waterland
4245c51f124SMoriah Waterland for (;;) {
4255c51f124SMoriah Waterland ssize_t bytesRead;
4265c51f124SMoriah Waterland
4275c51f124SMoriah Waterland /* read as much child data as there is available buffer space */
4285c51f124SMoriah Waterland
4295c51f124SMoriah Waterland bytesRead = read(ipipe[0], buffer + bufferIndex,
4305c51f124SMoriah Waterland bufferSize - bufferIndex);
4315c51f124SMoriah Waterland
4325c51f124SMoriah Waterland /* break out of read loop if end-of-file encountered */
4335c51f124SMoriah Waterland
4345c51f124SMoriah Waterland if (bytesRead == 0) {
4355c51f124SMoriah Waterland break;
4365c51f124SMoriah Waterland }
4375c51f124SMoriah Waterland
4385c51f124SMoriah Waterland /* if error, continue if recoverable, else break out of loop */
4395c51f124SMoriah Waterland
4405c51f124SMoriah Waterland if (bytesRead == -1) {
4415c51f124SMoriah Waterland /* try again: EAGAIN - insufficient resources */
4425c51f124SMoriah Waterland
4435c51f124SMoriah Waterland if (errno == EAGAIN) {
4445c51f124SMoriah Waterland continue;
4455c51f124SMoriah Waterland }
4465c51f124SMoriah Waterland
4475c51f124SMoriah Waterland /* try again: EINTR - interrupted system call */
4485c51f124SMoriah Waterland
4495c51f124SMoriah Waterland if (errno == EINTR) {
4505c51f124SMoriah Waterland continue;
4515c51f124SMoriah Waterland }
4525c51f124SMoriah Waterland
4535c51f124SMoriah Waterland /* break out of loop - error not recoverable */
4545c51f124SMoriah Waterland break;
4555c51f124SMoriah Waterland }
4565c51f124SMoriah Waterland
4575c51f124SMoriah Waterland /* at least 1 byte read: expand buffer if at end */
4585c51f124SMoriah Waterland
4595c51f124SMoriah Waterland bufferIndex += bytesRead;
4605c51f124SMoriah Waterland if (bufferIndex >= bufferSize) {
4615c51f124SMoriah Waterland buffer = realloc(buffer,
4625c51f124SMoriah Waterland bufferSize += PIPE_BUFFER_INCREMENT);
4635c51f124SMoriah Waterland (void) memset(buffer + bufferIndex, 0,
4645c51f124SMoriah Waterland bufferSize - bufferIndex);
4655c51f124SMoriah Waterland }
4665c51f124SMoriah Waterland }
4675c51f124SMoriah Waterland
4685c51f124SMoriah Waterland (void) close(ipipe[0]); /* Close read side of pipe */
4695c51f124SMoriah Waterland
4705c51f124SMoriah Waterland /* Get subprocess exit status */
4715c51f124SMoriah Waterland
4725c51f124SMoriah Waterland for (;;) {
4735c51f124SMoriah Waterland resultPid = waitpid(pid, &status, 0L);
4745c51f124SMoriah Waterland lerrno = (resultPid == -1 ? errno : 0);
4755c51f124SMoriah Waterland
4765c51f124SMoriah Waterland /* break loop if child process status reaped */
4775c51f124SMoriah Waterland
4785c51f124SMoriah Waterland if (resultPid != -1) {
4795c51f124SMoriah Waterland break;
4805c51f124SMoriah Waterland }
4815c51f124SMoriah Waterland
4825c51f124SMoriah Waterland /* break loop if not interrupted out of waitpid */
4835c51f124SMoriah Waterland
4845c51f124SMoriah Waterland if (errno != EINTR) {
4855c51f124SMoriah Waterland break;
4865c51f124SMoriah Waterland }
4875c51f124SMoriah Waterland }
4885c51f124SMoriah Waterland
4895c51f124SMoriah Waterland /*
4905c51f124SMoriah Waterland * If the child process terminated due to a call to exit(), then
4915c51f124SMoriah Waterland * set results equal to the 8-bit exit status of the child process;
4925c51f124SMoriah Waterland * otherwise, set the exit status to "-1" indicating that the child
4935c51f124SMoriah Waterland * exited via a signal.
4945c51f124SMoriah Waterland */
4955c51f124SMoriah Waterland
4965c51f124SMoriah Waterland *r_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
4975c51f124SMoriah Waterland
4985c51f124SMoriah Waterland /* return appropriate output */
4995c51f124SMoriah Waterland
5005c51f124SMoriah Waterland if (!*buffer) {
5015c51f124SMoriah Waterland /* No contents in output buffer - discard */
5025c51f124SMoriah Waterland free(buffer);
5035c51f124SMoriah Waterland } else if (r_results == (char **)NULL) {
5045c51f124SMoriah Waterland /* Not requested to return results - discard */
5055c51f124SMoriah Waterland free(buffer);
5065c51f124SMoriah Waterland } else {
5075c51f124SMoriah Waterland /* have output and request to return: pass to calling method */
5085c51f124SMoriah Waterland *r_results = buffer;
5095c51f124SMoriah Waterland }
5105c51f124SMoriah Waterland
5115c51f124SMoriah Waterland errno = lerrno;
5125c51f124SMoriah Waterland return (resultPid == -1 ? -1 : 0);
5135c51f124SMoriah Waterland }
5145c51f124SMoriah Waterland
5155c51f124SMoriah Waterland /*
5165c51f124SMoriah Waterland * Name: e_ExecCmdList
5175c51f124SMoriah Waterland * Synopsis: Execute Unix command and return results
5185c51f124SMoriah Waterland * Description: Execute a Unix command and return results and status
5195c51f124SMoriah Waterland * Arguments:
5205c51f124SMoriah Waterland * r_status - [RO, *RW] - (int *)
5215c51f124SMoriah Waterland * Return (exit) status from Unix command
5225c51f124SMoriah Waterland * r_results - [RO, *RW] - (char **)
5235c51f124SMoriah Waterland * Any output generated by the Unix command to stdout
5245c51f124SMoriah Waterland * and to stderr
5255c51f124SMoriah Waterland * == (char *)NULL if no output generated
5265c51f124SMoriah Waterland * a_inputFile - [RO, *RO] - (char *)
5275c51f124SMoriah Waterland * Pointer to character string representing file to be
5285c51f124SMoriah Waterland * used as "standard input" for the command.
5295c51f124SMoriah Waterland * == (char *)NULL to use "/dev/null" as standard input
5305c51f124SMoriah Waterland * a_cmd - [RO, *RO] - (char *)
5315c51f124SMoriah Waterland * Pointer to character string representing the full path
5325c51f124SMoriah Waterland * of the Unix command to execute
5335c51f124SMoriah Waterland * ... - [RO] (?)
5345c51f124SMoriah Waterland * Zero or more arguments to the Unix command
5355c51f124SMoriah Waterland * The argument list must be ended with (void *)NULL
5365c51f124SMoriah Waterland * Returns: int
5375c51f124SMoriah Waterland * == 0 - Command executed
5385c51f124SMoriah Waterland * Look at r_status for results of Unix command
5395c51f124SMoriah Waterland * != 0 - problems executing command
5405c51f124SMoriah Waterland * r_status and r_results have no meaning
5415c51f124SMoriah Waterland * NOTE: Any results returned is placed in new storage for the
5425c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
5435c51f124SMoriah Waterland * of the storage once the results are no longer needed.
5445c51f124SMoriah Waterland * NOTE: If LU_SUCCESS is returned, 'r_status' must be queried to
5455c51f124SMoriah Waterland * determine the results of the Unix command.
5465c51f124SMoriah Waterland */
5475c51f124SMoriah Waterland
5485c51f124SMoriah Waterland int
e_ExecCmdList(int * r_status,char ** r_results,char * a_inputFile,char * a_cmd,...)5495c51f124SMoriah Waterland e_ExecCmdList(int *r_status, char **r_results,
5505c51f124SMoriah Waterland char *a_inputFile, char *a_cmd, ...)
5515c51f124SMoriah Waterland {
5525c51f124SMoriah Waterland va_list ap; /* references variable argument list */
5535c51f124SMoriah Waterland char *array[MAX_EXEC_CMD_ARGS+1];
5545c51f124SMoriah Waterland int argno = 0;
5555c51f124SMoriah Waterland
5565c51f124SMoriah Waterland /*
5575c51f124SMoriah Waterland * Create argument array for exec system call
5585c51f124SMoriah Waterland */
5595c51f124SMoriah Waterland
5605c51f124SMoriah Waterland bzero(array, sizeof (array));
5615c51f124SMoriah Waterland
5625c51f124SMoriah Waterland va_start(ap, a_cmd); /* Begin variable argument processing */
5635c51f124SMoriah Waterland
5645c51f124SMoriah Waterland for (argno = 0; argno < MAX_EXEC_CMD_ARGS; argno++) {
5655c51f124SMoriah Waterland array[argno] = va_arg(ap, char *);
5665c51f124SMoriah Waterland if (array[argno] == (char *)NULL) {
5675c51f124SMoriah Waterland break;
5685c51f124SMoriah Waterland }
5695c51f124SMoriah Waterland }
5705c51f124SMoriah Waterland
5715c51f124SMoriah Waterland va_end(ap);
5725c51f124SMoriah Waterland return (e_ExecCmdArray(r_status, r_results, a_inputFile,
5735c51f124SMoriah Waterland a_cmd, array));
5745c51f124SMoriah Waterland }
575