1*9781SMoriah.Waterland@Sun.COM /* 2*9781SMoriah.Waterland@Sun.COM * CDDL HEADER START 3*9781SMoriah.Waterland@Sun.COM * 4*9781SMoriah.Waterland@Sun.COM * The contents of this file are subject to the terms of the 5*9781SMoriah.Waterland@Sun.COM * Common Development and Distribution License (the "License"). 6*9781SMoriah.Waterland@Sun.COM * You may not use this file except in compliance with the License. 7*9781SMoriah.Waterland@Sun.COM * 8*9781SMoriah.Waterland@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9781SMoriah.Waterland@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*9781SMoriah.Waterland@Sun.COM * See the License for the specific language governing permissions 11*9781SMoriah.Waterland@Sun.COM * and limitations under the License. 12*9781SMoriah.Waterland@Sun.COM * 13*9781SMoriah.Waterland@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*9781SMoriah.Waterland@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9781SMoriah.Waterland@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*9781SMoriah.Waterland@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*9781SMoriah.Waterland@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*9781SMoriah.Waterland@Sun.COM * 19*9781SMoriah.Waterland@Sun.COM * CDDL HEADER END 20*9781SMoriah.Waterland@Sun.COM */ 21*9781SMoriah.Waterland@Sun.COM 22*9781SMoriah.Waterland@Sun.COM /* 23*9781SMoriah.Waterland@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*9781SMoriah.Waterland@Sun.COM * Use is subject to license terms. 25*9781SMoriah.Waterland@Sun.COM */ 26*9781SMoriah.Waterland@Sun.COM 27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */ 29*9781SMoriah.Waterland@Sun.COM 30*9781SMoriah.Waterland@Sun.COM 31*9781SMoriah.Waterland@Sun.COM 32*9781SMoriah.Waterland@Sun.COM #include <stdio.h> 33*9781SMoriah.Waterland@Sun.COM #include <errno.h> 34*9781SMoriah.Waterland@Sun.COM #include <string.h> 35*9781SMoriah.Waterland@Sun.COM #include <strings.h> 36*9781SMoriah.Waterland@Sun.COM #include <signal.h> 37*9781SMoriah.Waterland@Sun.COM #include <fcntl.h> 38*9781SMoriah.Waterland@Sun.COM #include <stdlib.h> 39*9781SMoriah.Waterland@Sun.COM #include <unistd.h> 40*9781SMoriah.Waterland@Sun.COM #include <wait.h> 41*9781SMoriah.Waterland@Sun.COM #include <sys/types.h> 42*9781SMoriah.Waterland@Sun.COM #include "pkglib.h" 43*9781SMoriah.Waterland@Sun.COM #include "pkglocale.h" 44*9781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h" 45*9781SMoriah.Waterland@Sun.COM 46*9781SMoriah.Waterland@Sun.COM #ifndef _STDARG_H 47*9781SMoriah.Waterland@Sun.COM #include "stdarg.h" 48*9781SMoriah.Waterland@Sun.COM #endif 49*9781SMoriah.Waterland@Sun.COM 50*9781SMoriah.Waterland@Sun.COM /* 51*9781SMoriah.Waterland@Sun.COM * Private definitions 52*9781SMoriah.Waterland@Sun.COM */ 53*9781SMoriah.Waterland@Sun.COM 54*9781SMoriah.Waterland@Sun.COM /* Maximum number of arguments to pkg_ExecCmdList */ 55*9781SMoriah.Waterland@Sun.COM 56*9781SMoriah.Waterland@Sun.COM #define MAX_EXEC_CMD_ARGS 100 57*9781SMoriah.Waterland@Sun.COM 58*9781SMoriah.Waterland@Sun.COM /* Size of buffer increments when reading from pipe */ 59*9781SMoriah.Waterland@Sun.COM 60*9781SMoriah.Waterland@Sun.COM #define PIPE_BUFFER_INCREMENT 256 61*9781SMoriah.Waterland@Sun.COM 62*9781SMoriah.Waterland@Sun.COM static char errfile[L_tmpnam+1]; 63*9781SMoriah.Waterland@Sun.COM 64*9781SMoriah.Waterland@Sun.COM /* 65*9781SMoriah.Waterland@Sun.COM * This is the "argument array" definition that is returned by e_new_args and is 66*9781SMoriah.Waterland@Sun.COM * used by e_add_args, e_free_args, etc. 67*9781SMoriah.Waterland@Sun.COM */ 68*9781SMoriah.Waterland@Sun.COM 69*9781SMoriah.Waterland@Sun.COM struct _argArray_t { 70*9781SMoriah.Waterland@Sun.COM long _aaNumArgs; /* number of arguments set */ 71*9781SMoriah.Waterland@Sun.COM long _aaMaxArgs; /* number of arguments allocated */ 72*9781SMoriah.Waterland@Sun.COM char **_aaArgs; /* actual arguments */ 73*9781SMoriah.Waterland@Sun.COM }; 74*9781SMoriah.Waterland@Sun.COM 75*9781SMoriah.Waterland@Sun.COM typedef struct _argArray_t argArray_t; 76*9781SMoriah.Waterland@Sun.COM 77*9781SMoriah.Waterland@Sun.COM /* 78*9781SMoriah.Waterland@Sun.COM * Private Methods 79*9781SMoriah.Waterland@Sun.COM */ 80*9781SMoriah.Waterland@Sun.COM static void e_free_args(argArray_t *a_args); 81*9781SMoriah.Waterland@Sun.COM static argArray_t *e_new_args(int initialCount); 82*9781SMoriah.Waterland@Sun.COM /*PRINTFLIKE2*/ 83*9781SMoriah.Waterland@Sun.COM static boolean_t e_add_arg(argArray_t *a_args, char *a_format, ...); 84*9781SMoriah.Waterland@Sun.COM static int e_get_argc(argArray_t *a_args); 85*9781SMoriah.Waterland@Sun.COM static char **e_get_argv(argArray_t *a_args); 86*9781SMoriah.Waterland@Sun.COM 87*9781SMoriah.Waterland@Sun.COM 88*9781SMoriah.Waterland@Sun.COM /* 89*9781SMoriah.Waterland@Sun.COM * Public Methods 90*9781SMoriah.Waterland@Sun.COM */ 91*9781SMoriah.Waterland@Sun.COM 92*9781SMoriah.Waterland@Sun.COM 93*9781SMoriah.Waterland@Sun.COM void 94*9781SMoriah.Waterland@Sun.COM rpterr(void) 95*9781SMoriah.Waterland@Sun.COM { 96*9781SMoriah.Waterland@Sun.COM FILE *fp; 97*9781SMoriah.Waterland@Sun.COM int c; 98*9781SMoriah.Waterland@Sun.COM 99*9781SMoriah.Waterland@Sun.COM if (errfile[0]) { 100*9781SMoriah.Waterland@Sun.COM if (fp = fopen(errfile, "r")) { 101*9781SMoriah.Waterland@Sun.COM while ((c = getc(fp)) != EOF) 102*9781SMoriah.Waterland@Sun.COM putc(c, stderr); 103*9781SMoriah.Waterland@Sun.COM (void) fclose(fp); 104*9781SMoriah.Waterland@Sun.COM } 105*9781SMoriah.Waterland@Sun.COM (void) unlink(errfile); 106*9781SMoriah.Waterland@Sun.COM errfile[0] = '\0'; 107*9781SMoriah.Waterland@Sun.COM } 108*9781SMoriah.Waterland@Sun.COM } 109*9781SMoriah.Waterland@Sun.COM 110*9781SMoriah.Waterland@Sun.COM void 111*9781SMoriah.Waterland@Sun.COM ecleanup(void) 112*9781SMoriah.Waterland@Sun.COM { 113*9781SMoriah.Waterland@Sun.COM if (errfile[0]) { 114*9781SMoriah.Waterland@Sun.COM (void) unlink(errfile); 115*9781SMoriah.Waterland@Sun.COM errfile[0] = NULL; 116*9781SMoriah.Waterland@Sun.COM } 117*9781SMoriah.Waterland@Sun.COM } 118*9781SMoriah.Waterland@Sun.COM 119*9781SMoriah.Waterland@Sun.COM int 120*9781SMoriah.Waterland@Sun.COM esystem(char *cmd, int ifd, int ofd) 121*9781SMoriah.Waterland@Sun.COM { 122*9781SMoriah.Waterland@Sun.COM char *perrfile; 123*9781SMoriah.Waterland@Sun.COM int status = 0; 124*9781SMoriah.Waterland@Sun.COM pid_t pid; 125*9781SMoriah.Waterland@Sun.COM 126*9781SMoriah.Waterland@Sun.COM perrfile = tmpnam(NULL); 127*9781SMoriah.Waterland@Sun.COM if (perrfile == NULL) { 128*9781SMoriah.Waterland@Sun.COM progerr( 129*9781SMoriah.Waterland@Sun.COM pkg_gt("unable to create temp error file, errno=%d"), 130*9781SMoriah.Waterland@Sun.COM errno); 131*9781SMoriah.Waterland@Sun.COM return (-1); 132*9781SMoriah.Waterland@Sun.COM } 133*9781SMoriah.Waterland@Sun.COM (void) strlcpy(errfile, perrfile, sizeof (errfile)); 134*9781SMoriah.Waterland@Sun.COM 135*9781SMoriah.Waterland@Sun.COM /* flush standard i/o before creating new process */ 136*9781SMoriah.Waterland@Sun.COM 137*9781SMoriah.Waterland@Sun.COM (void) fflush(stderr); 138*9781SMoriah.Waterland@Sun.COM (void) fflush(stdout); 139*9781SMoriah.Waterland@Sun.COM 140*9781SMoriah.Waterland@Sun.COM /* 141*9781SMoriah.Waterland@Sun.COM * create new process to execute command in; 142*9781SMoriah.Waterland@Sun.COM * vfork() is being used to avoid duplicating the parents 143*9781SMoriah.Waterland@Sun.COM * memory space - this means that the child process may 144*9781SMoriah.Waterland@Sun.COM * not modify any of the parents memory including the 145*9781SMoriah.Waterland@Sun.COM * standard i/o descriptors - all the child can do is 146*9781SMoriah.Waterland@Sun.COM * adjust interrupts and open files as a prelude to a 147*9781SMoriah.Waterland@Sun.COM * call to exec(). 148*9781SMoriah.Waterland@Sun.COM */ 149*9781SMoriah.Waterland@Sun.COM 150*9781SMoriah.Waterland@Sun.COM pid = vfork(); 151*9781SMoriah.Waterland@Sun.COM if (pid == 0) { 152*9781SMoriah.Waterland@Sun.COM /* 153*9781SMoriah.Waterland@Sun.COM * this is the child process 154*9781SMoriah.Waterland@Sun.COM */ 155*9781SMoriah.Waterland@Sun.COM int i; 156*9781SMoriah.Waterland@Sun.COM 157*9781SMoriah.Waterland@Sun.COM /* reset any signals to default */ 158*9781SMoriah.Waterland@Sun.COM 159*9781SMoriah.Waterland@Sun.COM for (i = 0; i < NSIG; i++) { 160*9781SMoriah.Waterland@Sun.COM (void) sigset(i, SIG_DFL); 161*9781SMoriah.Waterland@Sun.COM } 162*9781SMoriah.Waterland@Sun.COM 163*9781SMoriah.Waterland@Sun.COM if (ifd > 0) { 164*9781SMoriah.Waterland@Sun.COM (void) dup2(ifd, STDIN_FILENO); 165*9781SMoriah.Waterland@Sun.COM } 166*9781SMoriah.Waterland@Sun.COM 167*9781SMoriah.Waterland@Sun.COM if (ofd >= 0 && ofd != STDOUT_FILENO) { 168*9781SMoriah.Waterland@Sun.COM (void) dup2(ofd, STDOUT_FILENO); 169*9781SMoriah.Waterland@Sun.COM } 170*9781SMoriah.Waterland@Sun.COM 171*9781SMoriah.Waterland@Sun.COM i = open(errfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); 172*9781SMoriah.Waterland@Sun.COM if (i >= 0) { 173*9781SMoriah.Waterland@Sun.COM dup2(i, STDERR_FILENO); 174*9781SMoriah.Waterland@Sun.COM } 175*9781SMoriah.Waterland@Sun.COM 176*9781SMoriah.Waterland@Sun.COM /* Close all open files except standard i/o */ 177*9781SMoriah.Waterland@Sun.COM 178*9781SMoriah.Waterland@Sun.COM closefrom(3); 179*9781SMoriah.Waterland@Sun.COM 180*9781SMoriah.Waterland@Sun.COM /* execute target executable */ 181*9781SMoriah.Waterland@Sun.COM 182*9781SMoriah.Waterland@Sun.COM execl("/sbin/sh", "/sbin/sh", "-c", cmd, NULL); 183*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt("exec of <%s> failed, errno=%d"), cmd, errno); 184*9781SMoriah.Waterland@Sun.COM _exit(99); 185*9781SMoriah.Waterland@Sun.COM } else if (pid < 0) { 186*9781SMoriah.Waterland@Sun.COM /* fork failed! */ 187*9781SMoriah.Waterland@Sun.COM 188*9781SMoriah.Waterland@Sun.COM logerr(pkg_gt("bad vfork(), errno=%d"), errno); 189*9781SMoriah.Waterland@Sun.COM return (-1); 190*9781SMoriah.Waterland@Sun.COM } 191*9781SMoriah.Waterland@Sun.COM 192*9781SMoriah.Waterland@Sun.COM /* 193*9781SMoriah.Waterland@Sun.COM * this is the parent process 194*9781SMoriah.Waterland@Sun.COM */ 195*9781SMoriah.Waterland@Sun.COM 196*9781SMoriah.Waterland@Sun.COM sighold(SIGINT); 197*9781SMoriah.Waterland@Sun.COM pid = waitpid(pid, &status, 0); 198*9781SMoriah.Waterland@Sun.COM sigrelse(SIGINT); 199*9781SMoriah.Waterland@Sun.COM 200*9781SMoriah.Waterland@Sun.COM if (pid < 0) { 201*9781SMoriah.Waterland@Sun.COM return (-1); /* probably interrupted */ 202*9781SMoriah.Waterland@Sun.COM } 203*9781SMoriah.Waterland@Sun.COM 204*9781SMoriah.Waterland@Sun.COM switch (status & 0177) { 205*9781SMoriah.Waterland@Sun.COM case 0: 206*9781SMoriah.Waterland@Sun.COM case 0177: 207*9781SMoriah.Waterland@Sun.COM status = status >> 8; 208*9781SMoriah.Waterland@Sun.COM /*FALLTHROUGH*/ 209*9781SMoriah.Waterland@Sun.COM 210*9781SMoriah.Waterland@Sun.COM default: 211*9781SMoriah.Waterland@Sun.COM /* terminated by a signal */ 212*9781SMoriah.Waterland@Sun.COM status = status & 0177; 213*9781SMoriah.Waterland@Sun.COM } 214*9781SMoriah.Waterland@Sun.COM 215*9781SMoriah.Waterland@Sun.COM if (status == 0) { 216*9781SMoriah.Waterland@Sun.COM ecleanup(); 217*9781SMoriah.Waterland@Sun.COM } 218*9781SMoriah.Waterland@Sun.COM 219*9781SMoriah.Waterland@Sun.COM return (status); 220*9781SMoriah.Waterland@Sun.COM } 221*9781SMoriah.Waterland@Sun.COM 222*9781SMoriah.Waterland@Sun.COM FILE * 223*9781SMoriah.Waterland@Sun.COM epopen(char *cmd, char *mode) 224*9781SMoriah.Waterland@Sun.COM { 225*9781SMoriah.Waterland@Sun.COM char *buffer, *perrfile; 226*9781SMoriah.Waterland@Sun.COM FILE *pp; 227*9781SMoriah.Waterland@Sun.COM size_t len; 228*9781SMoriah.Waterland@Sun.COM size_t alen; 229*9781SMoriah.Waterland@Sun.COM 230*9781SMoriah.Waterland@Sun.COM if (errfile[0]) { 231*9781SMoriah.Waterland@Sun.COM /* cleanup previous errfile */ 232*9781SMoriah.Waterland@Sun.COM unlink(errfile); 233*9781SMoriah.Waterland@Sun.COM } 234*9781SMoriah.Waterland@Sun.COM 235*9781SMoriah.Waterland@Sun.COM perrfile = tmpnam(NULL); 236*9781SMoriah.Waterland@Sun.COM if (perrfile == NULL) { 237*9781SMoriah.Waterland@Sun.COM progerr( 238*9781SMoriah.Waterland@Sun.COM pkg_gt("unable to create temp error file, errno=%d"), 239*9781SMoriah.Waterland@Sun.COM errno); 240*9781SMoriah.Waterland@Sun.COM return ((FILE *)0); 241*9781SMoriah.Waterland@Sun.COM } 242*9781SMoriah.Waterland@Sun.COM 243*9781SMoriah.Waterland@Sun.COM if (strlcpy(errfile, perrfile, sizeof (errfile)) > sizeof (errfile)) { 244*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt("file name max length %d; name is too long: %s"), 245*9781SMoriah.Waterland@Sun.COM sizeof (errfile), perrfile); 246*9781SMoriah.Waterland@Sun.COM return ((FILE *)0); 247*9781SMoriah.Waterland@Sun.COM } 248*9781SMoriah.Waterland@Sun.COM 249*9781SMoriah.Waterland@Sun.COM len = strlen(cmd)+6+strlen(errfile); 250*9781SMoriah.Waterland@Sun.COM buffer = (char *)calloc(len, sizeof (char)); 251*9781SMoriah.Waterland@Sun.COM if (buffer == NULL) { 252*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt("no memory in epopen(), errno=%d"), errno); 253*9781SMoriah.Waterland@Sun.COM return ((FILE *)0); 254*9781SMoriah.Waterland@Sun.COM } 255*9781SMoriah.Waterland@Sun.COM 256*9781SMoriah.Waterland@Sun.COM if (strchr(cmd, '|')) { 257*9781SMoriah.Waterland@Sun.COM alen = snprintf(buffer, len, "(%s) 2>%s", cmd, errfile); 258*9781SMoriah.Waterland@Sun.COM } else { 259*9781SMoriah.Waterland@Sun.COM alen = snprintf(buffer, len, "%s 2>%s", cmd, errfile); 260*9781SMoriah.Waterland@Sun.COM } 261*9781SMoriah.Waterland@Sun.COM 262*9781SMoriah.Waterland@Sun.COM if (alen > len) { 263*9781SMoriah.Waterland@Sun.COM progerr(pkg_gt("command max length %d; cmd is too long: %s"), 264*9781SMoriah.Waterland@Sun.COM len, cmd); 265*9781SMoriah.Waterland@Sun.COM return ((FILE *)0); 266*9781SMoriah.Waterland@Sun.COM } 267*9781SMoriah.Waterland@Sun.COM 268*9781SMoriah.Waterland@Sun.COM pp = popen(buffer, mode); 269*9781SMoriah.Waterland@Sun.COM 270*9781SMoriah.Waterland@Sun.COM free(buffer); 271*9781SMoriah.Waterland@Sun.COM return (pp); 272*9781SMoriah.Waterland@Sun.COM } 273*9781SMoriah.Waterland@Sun.COM 274*9781SMoriah.Waterland@Sun.COM int 275*9781SMoriah.Waterland@Sun.COM epclose(FILE *pp) 276*9781SMoriah.Waterland@Sun.COM { 277*9781SMoriah.Waterland@Sun.COM int n; 278*9781SMoriah.Waterland@Sun.COM 279*9781SMoriah.Waterland@Sun.COM n = pclose(pp); 280*9781SMoriah.Waterland@Sun.COM if (n == 0) 281*9781SMoriah.Waterland@Sun.COM ecleanup(); 282*9781SMoriah.Waterland@Sun.COM return (n); 283*9781SMoriah.Waterland@Sun.COM } 284*9781SMoriah.Waterland@Sun.COM 285*9781SMoriah.Waterland@Sun.COM /* 286*9781SMoriah.Waterland@Sun.COM * Name: e_ExecCmdArray 287*9781SMoriah.Waterland@Sun.COM * Synopsis: Execute Unix command and return results 288*9781SMoriah.Waterland@Sun.COM * Description: Execute a Unix command and return results and status 289*9781SMoriah.Waterland@Sun.COM * Arguments: 290*9781SMoriah.Waterland@Sun.COM * r_status - [RO, *RW] - (int *) 291*9781SMoriah.Waterland@Sun.COM * Return (exit) status from Unix command: 292*9781SMoriah.Waterland@Sun.COM * == -1 : child terminated with a signal 293*9781SMoriah.Waterland@Sun.COM * != -1 : lower 8-bit value child passed to exit() 294*9781SMoriah.Waterland@Sun.COM * r_results - [RO, *RW] - (char **) 295*9781SMoriah.Waterland@Sun.COM * Any output generated by the Unix command to stdout 296*9781SMoriah.Waterland@Sun.COM * and to stderr 297*9781SMoriah.Waterland@Sun.COM * == (char *)NULL if no output generated 298*9781SMoriah.Waterland@Sun.COM * a_inputFile - [RO, *RO] - (char *) 299*9781SMoriah.Waterland@Sun.COM * Pointer to character string representing file to be 300*9781SMoriah.Waterland@Sun.COM * used as "standard input" for the command. 301*9781SMoriah.Waterland@Sun.COM * == (char *)NULL to use "/dev/null" as standard input 302*9781SMoriah.Waterland@Sun.COM * a_cmd - [RO, *RO] - (char *) 303*9781SMoriah.Waterland@Sun.COM * Pointer to character string representing the full path 304*9781SMoriah.Waterland@Sun.COM * of the Unix command to execute 305*9781SMoriah.Waterland@Sun.COM * char **a_args - [RO, *RO] - (char **) 306*9781SMoriah.Waterland@Sun.COM * List of character strings representing the arguments 307*9781SMoriah.Waterland@Sun.COM * to be passed to the Unix command. The list must be 308*9781SMoriah.Waterland@Sun.COM * terminated with an element that is (char *)NULL 309*9781SMoriah.Waterland@Sun.COM * Returns: int 310*9781SMoriah.Waterland@Sun.COM * == 0 - Command executed 311*9781SMoriah.Waterland@Sun.COM * Look at r_status for results of Unix command 312*9781SMoriah.Waterland@Sun.COM * != 0 - problems executing command 313*9781SMoriah.Waterland@Sun.COM * r_status and r_results have no meaning; 314*9781SMoriah.Waterland@Sun.COM * r_status will be -1 315*9781SMoriah.Waterland@Sun.COM * r_results will be NULL 316*9781SMoriah.Waterland@Sun.COM * NOTE: Any results returned is placed in new storage for the 317*9781SMoriah.Waterland@Sun.COM * calling method. The caller must use 'free' to dispose 318*9781SMoriah.Waterland@Sun.COM * of the storage once the results are no longer needed. 319*9781SMoriah.Waterland@Sun.COM * NOTE: If 0 is returned, 'r_status' must be queried to 320*9781SMoriah.Waterland@Sun.COM * determine the results of the Unix command. 321*9781SMoriah.Waterland@Sun.COM * NOTE: The system "errno" value from immediately after waitpid() call 322*9781SMoriah.Waterland@Sun.COM * is preserved for the calling method to use to determine 323*9781SMoriah.Waterland@Sun.COM * the system reason why the operation failed. 324*9781SMoriah.Waterland@Sun.COM */ 325*9781SMoriah.Waterland@Sun.COM 326*9781SMoriah.Waterland@Sun.COM int 327*9781SMoriah.Waterland@Sun.COM e_ExecCmdArray(int *r_status, char **r_results, 328*9781SMoriah.Waterland@Sun.COM char *a_inputFile, char *a_cmd, char **a_args) 329*9781SMoriah.Waterland@Sun.COM { 330*9781SMoriah.Waterland@Sun.COM char *buffer; 331*9781SMoriah.Waterland@Sun.COM int bufferIndex; 332*9781SMoriah.Waterland@Sun.COM int bufferSize; 333*9781SMoriah.Waterland@Sun.COM int ipipe[2] = {0, 0}; 334*9781SMoriah.Waterland@Sun.COM pid_t pid; 335*9781SMoriah.Waterland@Sun.COM pid_t resultPid; 336*9781SMoriah.Waterland@Sun.COM int status; 337*9781SMoriah.Waterland@Sun.COM int lerrno; 338*9781SMoriah.Waterland@Sun.COM int stdinfile = -1; 339*9781SMoriah.Waterland@Sun.COM 340*9781SMoriah.Waterland@Sun.COM /* reset return results buffer pointer */ 341*9781SMoriah.Waterland@Sun.COM 342*9781SMoriah.Waterland@Sun.COM if (r_results != (char **)NULL) { 343*9781SMoriah.Waterland@Sun.COM *r_results = (char *)NULL; 344*9781SMoriah.Waterland@Sun.COM } 345*9781SMoriah.Waterland@Sun.COM 346*9781SMoriah.Waterland@Sun.COM *r_status = -1; 347*9781SMoriah.Waterland@Sun.COM 348*9781SMoriah.Waterland@Sun.COM /* 349*9781SMoriah.Waterland@Sun.COM * See if command exists 350*9781SMoriah.Waterland@Sun.COM */ 351*9781SMoriah.Waterland@Sun.COM 352*9781SMoriah.Waterland@Sun.COM if (access(a_cmd, F_OK|X_OK) != 0) { 353*9781SMoriah.Waterland@Sun.COM return (-1); 354*9781SMoriah.Waterland@Sun.COM } 355*9781SMoriah.Waterland@Sun.COM 356*9781SMoriah.Waterland@Sun.COM /* 357*9781SMoriah.Waterland@Sun.COM * See if input file exists 358*9781SMoriah.Waterland@Sun.COM */ 359*9781SMoriah.Waterland@Sun.COM 360*9781SMoriah.Waterland@Sun.COM if (a_inputFile != (char *)NULL) { 361*9781SMoriah.Waterland@Sun.COM stdinfile = open(a_inputFile, O_RDONLY); 362*9781SMoriah.Waterland@Sun.COM } else { 363*9781SMoriah.Waterland@Sun.COM stdinfile = open("/dev/null", O_RDONLY); /* stdin = /dev/null */ 364*9781SMoriah.Waterland@Sun.COM } 365*9781SMoriah.Waterland@Sun.COM 366*9781SMoriah.Waterland@Sun.COM if (stdinfile < 0) { 367*9781SMoriah.Waterland@Sun.COM return (-1); 368*9781SMoriah.Waterland@Sun.COM } 369*9781SMoriah.Waterland@Sun.COM 370*9781SMoriah.Waterland@Sun.COM /* 371*9781SMoriah.Waterland@Sun.COM * Create a pipe to be used to capture the command output 372*9781SMoriah.Waterland@Sun.COM */ 373*9781SMoriah.Waterland@Sun.COM 374*9781SMoriah.Waterland@Sun.COM if (pipe(ipipe) != 0) { 375*9781SMoriah.Waterland@Sun.COM (void) close(stdinfile); 376*9781SMoriah.Waterland@Sun.COM return (-1); 377*9781SMoriah.Waterland@Sun.COM } 378*9781SMoriah.Waterland@Sun.COM 379*9781SMoriah.Waterland@Sun.COM 380*9781SMoriah.Waterland@Sun.COM bufferSize = PIPE_BUFFER_INCREMENT; 381*9781SMoriah.Waterland@Sun.COM bufferIndex = 0; 382*9781SMoriah.Waterland@Sun.COM buffer = calloc(1, bufferSize); 383*9781SMoriah.Waterland@Sun.COM if (buffer == (char *)NULL) { 384*9781SMoriah.Waterland@Sun.COM (void) close(stdinfile); 385*9781SMoriah.Waterland@Sun.COM return (-1); 386*9781SMoriah.Waterland@Sun.COM } 387*9781SMoriah.Waterland@Sun.COM 388*9781SMoriah.Waterland@Sun.COM /* flush standard i/o before creating new process */ 389*9781SMoriah.Waterland@Sun.COM 390*9781SMoriah.Waterland@Sun.COM (void) fflush(stderr); 391*9781SMoriah.Waterland@Sun.COM (void) fflush(stdout); 392*9781SMoriah.Waterland@Sun.COM 393*9781SMoriah.Waterland@Sun.COM /* 394*9781SMoriah.Waterland@Sun.COM * create new process to execute command in; 395*9781SMoriah.Waterland@Sun.COM * vfork() is being used to avoid duplicating the parents 396*9781SMoriah.Waterland@Sun.COM * memory space - this means that the child process may 397*9781SMoriah.Waterland@Sun.COM * not modify any of the parents memory including the 398*9781SMoriah.Waterland@Sun.COM * standard i/o descriptors - all the child can do is 399*9781SMoriah.Waterland@Sun.COM * adjust interrupts and open files as a prelude to a 400*9781SMoriah.Waterland@Sun.COM * call to exec(). 401*9781SMoriah.Waterland@Sun.COM */ 402*9781SMoriah.Waterland@Sun.COM 403*9781SMoriah.Waterland@Sun.COM pid = vfork(); 404*9781SMoriah.Waterland@Sun.COM 405*9781SMoriah.Waterland@Sun.COM if (pid == 0) { 406*9781SMoriah.Waterland@Sun.COM /* 407*9781SMoriah.Waterland@Sun.COM * This is the forked (child) process ====================== 408*9781SMoriah.Waterland@Sun.COM */ 409*9781SMoriah.Waterland@Sun.COM 410*9781SMoriah.Waterland@Sun.COM int i; 411*9781SMoriah.Waterland@Sun.COM 412*9781SMoriah.Waterland@Sun.COM /* reset any signals to default */ 413*9781SMoriah.Waterland@Sun.COM 414*9781SMoriah.Waterland@Sun.COM for (i = 0; i < NSIG; i++) { 415*9781SMoriah.Waterland@Sun.COM (void) sigset(i, SIG_DFL); 416*9781SMoriah.Waterland@Sun.COM } 417*9781SMoriah.Waterland@Sun.COM 418*9781SMoriah.Waterland@Sun.COM /* assign stdin, stdout, stderr as appropriate */ 419*9781SMoriah.Waterland@Sun.COM 420*9781SMoriah.Waterland@Sun.COM (void) dup2(stdinfile, STDIN_FILENO); 421*9781SMoriah.Waterland@Sun.COM (void) close(ipipe[0]); /* close out pipe reader side */ 422*9781SMoriah.Waterland@Sun.COM (void) dup2(ipipe[1], STDOUT_FILENO); 423*9781SMoriah.Waterland@Sun.COM (void) dup2(ipipe[1], STDERR_FILENO); 424*9781SMoriah.Waterland@Sun.COM 425*9781SMoriah.Waterland@Sun.COM /* Close all open files except standard i/o */ 426*9781SMoriah.Waterland@Sun.COM 427*9781SMoriah.Waterland@Sun.COM closefrom(3); 428*9781SMoriah.Waterland@Sun.COM 429*9781SMoriah.Waterland@Sun.COM /* execute target executable */ 430*9781SMoriah.Waterland@Sun.COM 431*9781SMoriah.Waterland@Sun.COM (void) execvp(a_cmd, a_args); 432*9781SMoriah.Waterland@Sun.COM perror(a_cmd); /* Emit error msg - ends up in callers buffer */ 433*9781SMoriah.Waterland@Sun.COM _exit(0x00FE); 434*9781SMoriah.Waterland@Sun.COM } 435*9781SMoriah.Waterland@Sun.COM 436*9781SMoriah.Waterland@Sun.COM /* 437*9781SMoriah.Waterland@Sun.COM * This is the forking (parent) process ==================== 438*9781SMoriah.Waterland@Sun.COM */ 439*9781SMoriah.Waterland@Sun.COM 440*9781SMoriah.Waterland@Sun.COM (void) close(stdinfile); 441*9781SMoriah.Waterland@Sun.COM (void) close(ipipe[1]); /* Close write side of pipe */ 442*9781SMoriah.Waterland@Sun.COM 443*9781SMoriah.Waterland@Sun.COM /* 444*9781SMoriah.Waterland@Sun.COM * Spin reading data from the child into the buffer - when the read eofs 445*9781SMoriah.Waterland@Sun.COM * the child has exited 446*9781SMoriah.Waterland@Sun.COM */ 447*9781SMoriah.Waterland@Sun.COM 448*9781SMoriah.Waterland@Sun.COM for (;;) { 449*9781SMoriah.Waterland@Sun.COM ssize_t bytesRead; 450*9781SMoriah.Waterland@Sun.COM 451*9781SMoriah.Waterland@Sun.COM /* read as much child data as there is available buffer space */ 452*9781SMoriah.Waterland@Sun.COM 453*9781SMoriah.Waterland@Sun.COM bytesRead = read(ipipe[0], buffer + bufferIndex, 454*9781SMoriah.Waterland@Sun.COM bufferSize - bufferIndex); 455*9781SMoriah.Waterland@Sun.COM 456*9781SMoriah.Waterland@Sun.COM /* break out of read loop if end-of-file encountered */ 457*9781SMoriah.Waterland@Sun.COM 458*9781SMoriah.Waterland@Sun.COM if (bytesRead == 0) { 459*9781SMoriah.Waterland@Sun.COM break; 460*9781SMoriah.Waterland@Sun.COM } 461*9781SMoriah.Waterland@Sun.COM 462*9781SMoriah.Waterland@Sun.COM /* if error, continue if recoverable, else break out of loop */ 463*9781SMoriah.Waterland@Sun.COM 464*9781SMoriah.Waterland@Sun.COM if (bytesRead == -1) { 465*9781SMoriah.Waterland@Sun.COM /* try again: EAGAIN - insufficient resources */ 466*9781SMoriah.Waterland@Sun.COM 467*9781SMoriah.Waterland@Sun.COM if (errno == EAGAIN) { 468*9781SMoriah.Waterland@Sun.COM continue; 469*9781SMoriah.Waterland@Sun.COM } 470*9781SMoriah.Waterland@Sun.COM 471*9781SMoriah.Waterland@Sun.COM /* try again: EINTR - interrupted system call */ 472*9781SMoriah.Waterland@Sun.COM 473*9781SMoriah.Waterland@Sun.COM if (errno == EINTR) { 474*9781SMoriah.Waterland@Sun.COM continue; 475*9781SMoriah.Waterland@Sun.COM } 476*9781SMoriah.Waterland@Sun.COM 477*9781SMoriah.Waterland@Sun.COM /* break out of loop - error not recoverable */ 478*9781SMoriah.Waterland@Sun.COM break; 479*9781SMoriah.Waterland@Sun.COM } 480*9781SMoriah.Waterland@Sun.COM 481*9781SMoriah.Waterland@Sun.COM /* at least 1 byte read: expand buffer if at end */ 482*9781SMoriah.Waterland@Sun.COM 483*9781SMoriah.Waterland@Sun.COM bufferIndex += bytesRead; 484*9781SMoriah.Waterland@Sun.COM if (bufferIndex >= bufferSize) { 485*9781SMoriah.Waterland@Sun.COM buffer = realloc(buffer, 486*9781SMoriah.Waterland@Sun.COM bufferSize += PIPE_BUFFER_INCREMENT); 487*9781SMoriah.Waterland@Sun.COM (void) memset(buffer + bufferIndex, 0, 488*9781SMoriah.Waterland@Sun.COM bufferSize - bufferIndex); 489*9781SMoriah.Waterland@Sun.COM } 490*9781SMoriah.Waterland@Sun.COM } 491*9781SMoriah.Waterland@Sun.COM 492*9781SMoriah.Waterland@Sun.COM (void) close(ipipe[0]); /* Close read side of pipe */ 493*9781SMoriah.Waterland@Sun.COM 494*9781SMoriah.Waterland@Sun.COM /* Get subprocess exit status */ 495*9781SMoriah.Waterland@Sun.COM 496*9781SMoriah.Waterland@Sun.COM for (;;) { 497*9781SMoriah.Waterland@Sun.COM resultPid = waitpid(pid, &status, 0L); 498*9781SMoriah.Waterland@Sun.COM lerrno = (resultPid == -1 ? errno : 0); 499*9781SMoriah.Waterland@Sun.COM 500*9781SMoriah.Waterland@Sun.COM /* break loop if child process status reaped */ 501*9781SMoriah.Waterland@Sun.COM 502*9781SMoriah.Waterland@Sun.COM if (resultPid != -1) { 503*9781SMoriah.Waterland@Sun.COM break; 504*9781SMoriah.Waterland@Sun.COM } 505*9781SMoriah.Waterland@Sun.COM 506*9781SMoriah.Waterland@Sun.COM /* break loop if not interrupted out of waitpid */ 507*9781SMoriah.Waterland@Sun.COM 508*9781SMoriah.Waterland@Sun.COM if (errno != EINTR) { 509*9781SMoriah.Waterland@Sun.COM break; 510*9781SMoriah.Waterland@Sun.COM } 511*9781SMoriah.Waterland@Sun.COM } 512*9781SMoriah.Waterland@Sun.COM 513*9781SMoriah.Waterland@Sun.COM /* 514*9781SMoriah.Waterland@Sun.COM * If the child process terminated due to a call to exit(), then 515*9781SMoriah.Waterland@Sun.COM * set results equal to the 8-bit exit status of the child process; 516*9781SMoriah.Waterland@Sun.COM * otherwise, set the exit status to "-1" indicating that the child 517*9781SMoriah.Waterland@Sun.COM * exited via a signal. 518*9781SMoriah.Waterland@Sun.COM */ 519*9781SMoriah.Waterland@Sun.COM 520*9781SMoriah.Waterland@Sun.COM *r_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; 521*9781SMoriah.Waterland@Sun.COM 522*9781SMoriah.Waterland@Sun.COM /* return appropriate output */ 523*9781SMoriah.Waterland@Sun.COM 524*9781SMoriah.Waterland@Sun.COM if (!*buffer) { 525*9781SMoriah.Waterland@Sun.COM /* No contents in output buffer - discard */ 526*9781SMoriah.Waterland@Sun.COM free(buffer); 527*9781SMoriah.Waterland@Sun.COM } else if (r_results == (char **)NULL) { 528*9781SMoriah.Waterland@Sun.COM /* Not requested to return results - discard */ 529*9781SMoriah.Waterland@Sun.COM free(buffer); 530*9781SMoriah.Waterland@Sun.COM } else { 531*9781SMoriah.Waterland@Sun.COM /* have output and request to return: pass to calling method */ 532*9781SMoriah.Waterland@Sun.COM *r_results = buffer; 533*9781SMoriah.Waterland@Sun.COM } 534*9781SMoriah.Waterland@Sun.COM 535*9781SMoriah.Waterland@Sun.COM errno = lerrno; 536*9781SMoriah.Waterland@Sun.COM return (resultPid == -1 ? -1 : 0); 537*9781SMoriah.Waterland@Sun.COM } 538*9781SMoriah.Waterland@Sun.COM 539*9781SMoriah.Waterland@Sun.COM /* 540*9781SMoriah.Waterland@Sun.COM * Name: e_ExecCmdList 541*9781SMoriah.Waterland@Sun.COM * Synopsis: Execute Unix command and return results 542*9781SMoriah.Waterland@Sun.COM * Description: Execute a Unix command and return results and status 543*9781SMoriah.Waterland@Sun.COM * Arguments: 544*9781SMoriah.Waterland@Sun.COM * r_status - [RO, *RW] - (int *) 545*9781SMoriah.Waterland@Sun.COM * Return (exit) status from Unix command 546*9781SMoriah.Waterland@Sun.COM * r_results - [RO, *RW] - (char **) 547*9781SMoriah.Waterland@Sun.COM * Any output generated by the Unix command to stdout 548*9781SMoriah.Waterland@Sun.COM * and to stderr 549*9781SMoriah.Waterland@Sun.COM * == (char *)NULL if no output generated 550*9781SMoriah.Waterland@Sun.COM * a_inputFile - [RO, *RO] - (char *) 551*9781SMoriah.Waterland@Sun.COM * Pointer to character string representing file to be 552*9781SMoriah.Waterland@Sun.COM * used as "standard input" for the command. 553*9781SMoriah.Waterland@Sun.COM * == (char *)NULL to use "/dev/null" as standard input 554*9781SMoriah.Waterland@Sun.COM * a_cmd - [RO, *RO] - (char *) 555*9781SMoriah.Waterland@Sun.COM * Pointer to character string representing the full path 556*9781SMoriah.Waterland@Sun.COM * of the Unix command to execute 557*9781SMoriah.Waterland@Sun.COM * ... - [RO] (?) 558*9781SMoriah.Waterland@Sun.COM * Zero or more arguments to the Unix command 559*9781SMoriah.Waterland@Sun.COM * The argument list must be ended with (void *)NULL 560*9781SMoriah.Waterland@Sun.COM * Returns: int 561*9781SMoriah.Waterland@Sun.COM * == 0 - Command executed 562*9781SMoriah.Waterland@Sun.COM * Look at r_status for results of Unix command 563*9781SMoriah.Waterland@Sun.COM * != 0 - problems executing command 564*9781SMoriah.Waterland@Sun.COM * r_status and r_results have no meaning 565*9781SMoriah.Waterland@Sun.COM * NOTE: Any results returned is placed in new storage for the 566*9781SMoriah.Waterland@Sun.COM * calling method. The caller must use 'free' to dispose 567*9781SMoriah.Waterland@Sun.COM * of the storage once the results are no longer needed. 568*9781SMoriah.Waterland@Sun.COM * NOTE: If LU_SUCCESS is returned, 'r_status' must be queried to 569*9781SMoriah.Waterland@Sun.COM * determine the results of the Unix command. 570*9781SMoriah.Waterland@Sun.COM */ 571*9781SMoriah.Waterland@Sun.COM 572*9781SMoriah.Waterland@Sun.COM int 573*9781SMoriah.Waterland@Sun.COM e_ExecCmdList(int *r_status, char **r_results, 574*9781SMoriah.Waterland@Sun.COM char *a_inputFile, char *a_cmd, ...) 575*9781SMoriah.Waterland@Sun.COM { 576*9781SMoriah.Waterland@Sun.COM va_list ap; /* references variable argument list */ 577*9781SMoriah.Waterland@Sun.COM char *array[MAX_EXEC_CMD_ARGS+1]; 578*9781SMoriah.Waterland@Sun.COM int argno = 0; 579*9781SMoriah.Waterland@Sun.COM 580*9781SMoriah.Waterland@Sun.COM /* 581*9781SMoriah.Waterland@Sun.COM * Create argument array for exec system call 582*9781SMoriah.Waterland@Sun.COM */ 583*9781SMoriah.Waterland@Sun.COM 584*9781SMoriah.Waterland@Sun.COM bzero(array, sizeof (array)); 585*9781SMoriah.Waterland@Sun.COM 586*9781SMoriah.Waterland@Sun.COM va_start(ap, a_cmd); /* Begin variable argument processing */ 587*9781SMoriah.Waterland@Sun.COM 588*9781SMoriah.Waterland@Sun.COM for (argno = 0; argno < MAX_EXEC_CMD_ARGS; argno++) { 589*9781SMoriah.Waterland@Sun.COM array[argno] = va_arg(ap, char *); 590*9781SMoriah.Waterland@Sun.COM if (array[argno] == (char *)NULL) { 591*9781SMoriah.Waterland@Sun.COM break; 592*9781SMoriah.Waterland@Sun.COM } 593*9781SMoriah.Waterland@Sun.COM } 594*9781SMoriah.Waterland@Sun.COM 595*9781SMoriah.Waterland@Sun.COM va_end(ap); 596*9781SMoriah.Waterland@Sun.COM return (e_ExecCmdArray(r_status, r_results, a_inputFile, 597*9781SMoriah.Waterland@Sun.COM a_cmd, array)); 598*9781SMoriah.Waterland@Sun.COM } 599*9781SMoriah.Waterland@Sun.COM 600*9781SMoriah.Waterland@Sun.COM /* 601*9781SMoriah.Waterland@Sun.COM * Name: e_new_args 602*9781SMoriah.Waterland@Sun.COM * Description: create a new argument array for use in exec() calls 603*9781SMoriah.Waterland@Sun.COM * Arguments: initialCount - [RO, *RO] - (int) 604*9781SMoriah.Waterland@Sun.COM * Initial number of elements to populate the 605*9781SMoriah.Waterland@Sun.COM * argument array with - use best guess 606*9781SMoriah.Waterland@Sun.COM * Returns: argArray_t * 607*9781SMoriah.Waterland@Sun.COM * Pointer to argument array that can be used in other 608*9781SMoriah.Waterland@Sun.COM * functions that accept it as an argument 609*9781SMoriah.Waterland@Sun.COM * == (argArray_t *)NULL - error 610*9781SMoriah.Waterland@Sun.COM * NOTE: you must call e_free_args() when the returned argument array is 611*9781SMoriah.Waterland@Sun.COM * no longer needed so that all storage used can be freed up. 612*9781SMoriah.Waterland@Sun.COM */ 613*9781SMoriah.Waterland@Sun.COM 614*9781SMoriah.Waterland@Sun.COM argArray_t * 615*9781SMoriah.Waterland@Sun.COM e_new_args(int initialCount) 616*9781SMoriah.Waterland@Sun.COM { 617*9781SMoriah.Waterland@Sun.COM argArray_t *aa; 618*9781SMoriah.Waterland@Sun.COM 619*9781SMoriah.Waterland@Sun.COM /* allocate new argument array structure */ 620*9781SMoriah.Waterland@Sun.COM 621*9781SMoriah.Waterland@Sun.COM aa = (argArray_t *)calloc(1, sizeof (argArray_t)); 622*9781SMoriah.Waterland@Sun.COM if (aa == (argArray_t *)NULL) { 623*9781SMoriah.Waterland@Sun.COM progerr(ERR_MALLOC, strerror(errno), sizeof (argArray_t), 624*9781SMoriah.Waterland@Sun.COM "<argArray_t>"); 625*9781SMoriah.Waterland@Sun.COM return ((argArray_t *)NULL); 626*9781SMoriah.Waterland@Sun.COM } 627*9781SMoriah.Waterland@Sun.COM 628*9781SMoriah.Waterland@Sun.COM /* allocate initial argument array */ 629*9781SMoriah.Waterland@Sun.COM 630*9781SMoriah.Waterland@Sun.COM aa->_aaArgs = (char **)calloc(initialCount+1, sizeof (char *)); 631*9781SMoriah.Waterland@Sun.COM if (aa->_aaArgs == (char **)NULL) { 632*9781SMoriah.Waterland@Sun.COM progerr(ERR_MALLOC, strerror(errno), 633*9781SMoriah.Waterland@Sun.COM (initialCount+1)*sizeof (char *), "<char **>"); 634*9781SMoriah.Waterland@Sun.COM return ((argArray_t *)NULL); 635*9781SMoriah.Waterland@Sun.COM } 636*9781SMoriah.Waterland@Sun.COM 637*9781SMoriah.Waterland@Sun.COM /* initialize argument indexes */ 638*9781SMoriah.Waterland@Sun.COM 639*9781SMoriah.Waterland@Sun.COM aa->_aaNumArgs = 0; 640*9781SMoriah.Waterland@Sun.COM aa->_aaMaxArgs = initialCount; 641*9781SMoriah.Waterland@Sun.COM 642*9781SMoriah.Waterland@Sun.COM return (aa); 643*9781SMoriah.Waterland@Sun.COM } 644*9781SMoriah.Waterland@Sun.COM 645*9781SMoriah.Waterland@Sun.COM /* 646*9781SMoriah.Waterland@Sun.COM * Name: e_add_arg 647*9781SMoriah.Waterland@Sun.COM * Description: add new argument to argument array for use in exec() calls 648*9781SMoriah.Waterland@Sun.COM * Arguments: a_args - [RO, *RW] - (argArray_t *) 649*9781SMoriah.Waterland@Sun.COM * Pointer to argument array (previously allocated via 650*9781SMoriah.Waterland@Sun.COM * a call to e_new_args) to add the argument to 651*9781SMoriah.Waterland@Sun.COM * a_format - [RO, *RO] - (char *) 652*9781SMoriah.Waterland@Sun.COM * Pointer to "printf" style format argument 653*9781SMoriah.Waterland@Sun.COM * ... - [RO, *RO] - (varies) 654*9781SMoriah.Waterland@Sun.COM * Arguments as appropriate for format statement 655*9781SMoriah.Waterland@Sun.COM * Returns: boolean_t 656*9781SMoriah.Waterland@Sun.COM * B_TRUE - success 657*9781SMoriah.Waterland@Sun.COM * B_FALSE - failure 658*9781SMoriah.Waterland@Sun.COM * Examples: 659*9781SMoriah.Waterland@Sun.COM * - to add an argument that specifies a file descriptor: 660*9781SMoriah.Waterland@Sun.COM * int fd; 661*9781SMoriah.Waterland@Sun.COM * e_add_arg(aa, "/proc/self/fd/%d", fd); 662*9781SMoriah.Waterland@Sun.COM * - to add a flag or other known text: 663*9781SMoriah.Waterland@Sun.COM * e_add_arg(aa, "-s") 664*9781SMoriah.Waterland@Sun.COM * - to add random text: 665*9781SMoriah.Waterland@Sun.COM * char *random_text; 666*9781SMoriah.Waterland@Sun.COM * e_add_arg(aa, "%s", random_text); 667*9781SMoriah.Waterland@Sun.COM */ 668*9781SMoriah.Waterland@Sun.COM 669*9781SMoriah.Waterland@Sun.COM /*PRINTFLIKE2*/ 670*9781SMoriah.Waterland@Sun.COM boolean_t 671*9781SMoriah.Waterland@Sun.COM e_add_arg(argArray_t *a_args, char *a_format, ...) 672*9781SMoriah.Waterland@Sun.COM { 673*9781SMoriah.Waterland@Sun.COM char *rstr = (char *)NULL; 674*9781SMoriah.Waterland@Sun.COM char bfr[MAX_CANON]; 675*9781SMoriah.Waterland@Sun.COM size_t vres = 0; 676*9781SMoriah.Waterland@Sun.COM va_list ap; 677*9781SMoriah.Waterland@Sun.COM 678*9781SMoriah.Waterland@Sun.COM /* 679*9781SMoriah.Waterland@Sun.COM * double argument array if array is full 680*9781SMoriah.Waterland@Sun.COM */ 681*9781SMoriah.Waterland@Sun.COM 682*9781SMoriah.Waterland@Sun.COM if (a_args->_aaNumArgs >= a_args->_aaMaxArgs) { 683*9781SMoriah.Waterland@Sun.COM int newMax; 684*9781SMoriah.Waterland@Sun.COM char **newArgs; 685*9781SMoriah.Waterland@Sun.COM 686*9781SMoriah.Waterland@Sun.COM newMax = a_args->_aaMaxArgs * 2; 687*9781SMoriah.Waterland@Sun.COM newArgs = (char **)realloc(a_args->_aaArgs, 688*9781SMoriah.Waterland@Sun.COM (newMax+1) * sizeof (char *)); 689*9781SMoriah.Waterland@Sun.COM if (newArgs == (char **)NULL) { 690*9781SMoriah.Waterland@Sun.COM progerr(ERR_MALLOC, strerror(errno), 691*9781SMoriah.Waterland@Sun.COM ((newMax+1) * sizeof (char *)), "<char **>"); 692*9781SMoriah.Waterland@Sun.COM return (B_FALSE); 693*9781SMoriah.Waterland@Sun.COM } 694*9781SMoriah.Waterland@Sun.COM a_args->_aaArgs = newArgs; 695*9781SMoriah.Waterland@Sun.COM a_args->_aaMaxArgs = newMax; 696*9781SMoriah.Waterland@Sun.COM } 697*9781SMoriah.Waterland@Sun.COM 698*9781SMoriah.Waterland@Sun.COM /* determine size of argument to add to list */ 699*9781SMoriah.Waterland@Sun.COM 700*9781SMoriah.Waterland@Sun.COM va_start(ap, a_format); 701*9781SMoriah.Waterland@Sun.COM vres = vsnprintf(bfr, sizeof (bfr), a_format, ap); 702*9781SMoriah.Waterland@Sun.COM va_end(ap); 703*9781SMoriah.Waterland@Sun.COM 704*9781SMoriah.Waterland@Sun.COM /* if it fit in the built in buffer, use that */ 705*9781SMoriah.Waterland@Sun.COM if (vres < sizeof (bfr)) { 706*9781SMoriah.Waterland@Sun.COM /* dup text already generated in bfr */ 707*9781SMoriah.Waterland@Sun.COM rstr = strdup(bfr); 708*9781SMoriah.Waterland@Sun.COM if (rstr == (char *)NULL) { 709*9781SMoriah.Waterland@Sun.COM progerr(ERR_MALLOC, strerror(errno), vres+2, 710*9781SMoriah.Waterland@Sun.COM "<char *>"); 711*9781SMoriah.Waterland@Sun.COM return (B_FALSE); 712*9781SMoriah.Waterland@Sun.COM } 713*9781SMoriah.Waterland@Sun.COM } else { 714*9781SMoriah.Waterland@Sun.COM /* allocate space for argument to add */ 715*9781SMoriah.Waterland@Sun.COM 716*9781SMoriah.Waterland@Sun.COM rstr = (char *)malloc(vres+2); 717*9781SMoriah.Waterland@Sun.COM if (rstr == (char *)NULL) { 718*9781SMoriah.Waterland@Sun.COM progerr(ERR_MALLOC, strerror(errno), vres+2, 719*9781SMoriah.Waterland@Sun.COM "<char *>"); 720*9781SMoriah.Waterland@Sun.COM return (B_FALSE); 721*9781SMoriah.Waterland@Sun.COM } 722*9781SMoriah.Waterland@Sun.COM 723*9781SMoriah.Waterland@Sun.COM /* generate argument to add */ 724*9781SMoriah.Waterland@Sun.COM 725*9781SMoriah.Waterland@Sun.COM va_start(ap, a_format); 726*9781SMoriah.Waterland@Sun.COM vres = vsnprintf(rstr, vres+1, a_format, ap); 727*9781SMoriah.Waterland@Sun.COM va_end(ap); 728*9781SMoriah.Waterland@Sun.COM } 729*9781SMoriah.Waterland@Sun.COM 730*9781SMoriah.Waterland@Sun.COM /* add argument to the end of the argument array */ 731*9781SMoriah.Waterland@Sun.COM 732*9781SMoriah.Waterland@Sun.COM a_args->_aaArgs[a_args->_aaNumArgs++] = rstr; 733*9781SMoriah.Waterland@Sun.COM a_args->_aaArgs[a_args->_aaNumArgs] = (char *)NULL; 734*9781SMoriah.Waterland@Sun.COM 735*9781SMoriah.Waterland@Sun.COM return (B_TRUE); 736*9781SMoriah.Waterland@Sun.COM } 737*9781SMoriah.Waterland@Sun.COM 738*9781SMoriah.Waterland@Sun.COM /* 739*9781SMoriah.Waterland@Sun.COM * Name: e_get_argv 740*9781SMoriah.Waterland@Sun.COM * Description: return (char **)argv pointer from argument array 741*9781SMoriah.Waterland@Sun.COM * Arguments: a_args - [RO, *RW] - (argArray_t *) 742*9781SMoriah.Waterland@Sun.COM * Pointer to argument array (previously allocated via 743*9781SMoriah.Waterland@Sun.COM * a call to e_new_args) to return argv pointer for 744*9781SMoriah.Waterland@Sun.COM * Returns: char ** 745*9781SMoriah.Waterland@Sun.COM * Pointer to (char **)argv pointer suitable for use 746*9781SMoriah.Waterland@Sun.COM * in an exec*() call 747*9781SMoriah.Waterland@Sun.COM * NOTE: the actual character array is always terminated with a (char *)NULL 748*9781SMoriah.Waterland@Sun.COM */ 749*9781SMoriah.Waterland@Sun.COM 750*9781SMoriah.Waterland@Sun.COM char ** 751*9781SMoriah.Waterland@Sun.COM e_get_argv(argArray_t *a_args) 752*9781SMoriah.Waterland@Sun.COM { 753*9781SMoriah.Waterland@Sun.COM return (a_args->_aaArgs); 754*9781SMoriah.Waterland@Sun.COM } 755*9781SMoriah.Waterland@Sun.COM 756*9781SMoriah.Waterland@Sun.COM /* 757*9781SMoriah.Waterland@Sun.COM * Name: e_get_argc 758*9781SMoriah.Waterland@Sun.COM * Description: return (int) argc count from argument array 759*9781SMoriah.Waterland@Sun.COM * Arguments: a_args - [RO, *RW] - (argArray_t *) 760*9781SMoriah.Waterland@Sun.COM * Pointer to argument array (previously allocated via 761*9781SMoriah.Waterland@Sun.COM * a call to e_new_args) to return argc count for 762*9781SMoriah.Waterland@Sun.COM * Returns: int 763*9781SMoriah.Waterland@Sun.COM * Count of the number of arguments in the argument array 764*9781SMoriah.Waterland@Sun.COM * suitable for use in an exec*() call 765*9781SMoriah.Waterland@Sun.COM */ 766*9781SMoriah.Waterland@Sun.COM 767*9781SMoriah.Waterland@Sun.COM int 768*9781SMoriah.Waterland@Sun.COM e_get_argc(argArray_t *a_args) 769*9781SMoriah.Waterland@Sun.COM { 770*9781SMoriah.Waterland@Sun.COM return (a_args->_aaNumArgs); 771*9781SMoriah.Waterland@Sun.COM } 772*9781SMoriah.Waterland@Sun.COM 773*9781SMoriah.Waterland@Sun.COM /* 774*9781SMoriah.Waterland@Sun.COM * Name: e_free_args 775*9781SMoriah.Waterland@Sun.COM * Description: free all storage contained in an argument array previously 776*9781SMoriah.Waterland@Sun.COM * allocated by a call to e_new_args 777*9781SMoriah.Waterland@Sun.COM * Arguments: a_args - [RO, *RW] - (argArray_t *) 778*9781SMoriah.Waterland@Sun.COM * Pointer to argument array (previously allocated via 779*9781SMoriah.Waterland@Sun.COM * a call to e_new_args) to free 780*9781SMoriah.Waterland@Sun.COM * Returns: void 781*9781SMoriah.Waterland@Sun.COM * NOTE: preserves errno (usually called right after e_execCmd*()) 782*9781SMoriah.Waterland@Sun.COM */ 783*9781SMoriah.Waterland@Sun.COM 784*9781SMoriah.Waterland@Sun.COM void 785*9781SMoriah.Waterland@Sun.COM e_free_args(argArray_t *a_args) 786*9781SMoriah.Waterland@Sun.COM { 787*9781SMoriah.Waterland@Sun.COM int i; 788*9781SMoriah.Waterland@Sun.COM int lerrno = errno; 789*9781SMoriah.Waterland@Sun.COM 790*9781SMoriah.Waterland@Sun.COM /* free all arguments in the argument array */ 791*9781SMoriah.Waterland@Sun.COM 792*9781SMoriah.Waterland@Sun.COM for (i = (a_args->_aaNumArgs-1); i >= 0; i--) { 793*9781SMoriah.Waterland@Sun.COM (void) free(a_args->_aaArgs[i]); 794*9781SMoriah.Waterland@Sun.COM a_args->_aaArgs[i] = (char *)NULL; 795*9781SMoriah.Waterland@Sun.COM } 796*9781SMoriah.Waterland@Sun.COM 797*9781SMoriah.Waterland@Sun.COM /* free argument array */ 798*9781SMoriah.Waterland@Sun.COM 799*9781SMoriah.Waterland@Sun.COM (void) free(a_args->_aaArgs); 800*9781SMoriah.Waterland@Sun.COM 801*9781SMoriah.Waterland@Sun.COM /* free argument array structure */ 802*9781SMoriah.Waterland@Sun.COM 803*9781SMoriah.Waterland@Sun.COM (void) free(a_args); 804*9781SMoriah.Waterland@Sun.COM 805*9781SMoriah.Waterland@Sun.COM /* restore errno */ 806*9781SMoriah.Waterland@Sun.COM 807*9781SMoriah.Waterland@Sun.COM errno = lerrno; 808*9781SMoriah.Waterland@Sun.COM } 809