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 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 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 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 * 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 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 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 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