1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 28 /* 29 * Module: zones_args.c 30 * Group: libinstzones 31 * Description: Private functions used by zones library functions to manipulate 32 * argument lists 33 * 34 * Public Methods: 35 * 36 * _z_add_arg - add new argument to argument array for use in exec() calls 37 * _z_free_args - free all storage contained in an argument array previously 38 * _z_get_argc - return (int) argc count from argument array 39 * _z_get_argv - return (char **)argv pointer from argument array 40 * _z_new_args - create a new argument array for use in exec() calls 41 */ 42 43 /* 44 * System includes 45 */ 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <unistd.h> 50 #include <fcntl.h> 51 #include <ctype.h> 52 #include <sys/types.h> 53 #include <sys/param.h> 54 #include <string.h> 55 #include <strings.h> 56 #include <stdarg.h> 57 #include <limits.h> 58 #include <errno.h> 59 #include <stropts.h> 60 #include <libintl.h> 61 #include <locale.h> 62 #include <assert.h> 63 64 /* 65 * local includes 66 */ 67 68 #include "instzones_lib.h" 69 #include "zones_strings.h" 70 71 /* 72 * Private structures 73 */ 74 75 /* 76 * Library Function Prototypes 77 */ 78 79 /* 80 * Local Function Prototypes 81 */ 82 83 /* 84 * Global internal (private) declarations 85 */ 86 87 /* 88 * ***************************************************************************** 89 * global external (public) functions 90 * ***************************************************************************** 91 */ 92 93 /* 94 * Name: _z_add_arg 95 * Description: add new argument to argument array for use in exec() calls 96 * Arguments: a_args - [RO, *RW] - (argArray_t *) 97 * Pointer to argument array (previously allocated via 98 * a call to _z_new_args) to add the argument to 99 * a_format - [RO, *RO] - (char *) 100 * Pointer to "printf(3C)" style format argument 101 * ... - [RO, *RO] - (varies) 102 * Arguments as appropriate for format argument specified 103 * Returns: boolean_t 104 * B_TRUE - success 105 * B_FALSE - failure 106 * Examples: 107 * - to add an argument that specifies a file descriptor: 108 * int fd; 109 * _z_add_arg(aa, "/proc/self/fd/%d", fd); 110 * - to add a flag or other known text: 111 * _z_add_arg(aa, "-s") 112 * - to add random text: 113 * char *random_text; 114 * _z_add_arg(aa, "%s", random_text); 115 */ 116 117 /*PRINTFLIKE2*/ 118 boolean_t 119 _z_add_arg(argArray_t *a_args, char *a_format, ...) 120 { 121 char *rstr = NULL; 122 char bfr[MAX_CANON]; 123 size_t vres = 0; 124 va_list ap; 125 126 /* entry assertions */ 127 128 assert(a_args != NULL); 129 assert(a_format != NULL); 130 assert(*a_format != '\0'); 131 132 /* 133 * double argument array if array is full 134 */ 135 136 if (a_args->_aaNumArgs >= a_args->_aaMaxArgs) { 137 int newMax; 138 char **newArgs; 139 140 newMax = a_args->_aaMaxArgs * 2; 141 newArgs = (char **)_z_realloc(a_args->_aaArgs, 142 (newMax+1) * sizeof (char *)); 143 a_args->_aaArgs = newArgs; 144 a_args->_aaMaxArgs = newMax; 145 } 146 147 /* 148 * determine size of argument to add to list 149 */ 150 151 va_start(ap, a_format); 152 vres = vsnprintf(bfr, sizeof (bfr), a_format, ap); 153 va_end(ap); 154 155 /* 156 * use the expanded argument if it will fit in the built in buffer, 157 * otherwise, allocate space to hold the argument 158 */ 159 160 if (vres < sizeof (bfr)) { 161 /* duplicate text already generated in buffer */ 162 rstr = _z_strdup(bfr); 163 } else { 164 /* allocate new space for argument to add */ 165 166 rstr = (char *)_z_malloc(vres+2); 167 168 /* generate argument to add */ 169 170 va_start(ap, a_format); 171 vres = vsnprintf(rstr, vres+1, a_format, ap); 172 va_end(ap); 173 } 174 175 /* add argument to the end of the argument array */ 176 177 a_args->_aaArgs[a_args->_aaNumArgs++] = rstr; 178 a_args->_aaArgs[a_args->_aaNumArgs] = NULL; 179 180 /* successful - return */ 181 182 return (B_TRUE); 183 } 184 185 /* 186 * Name: _z_free_args 187 * Description: free all storage contained in an argument array previously 188 * allocated by a call to _z_new_args 189 * Arguments: a_args - [RO, *RW] - (argArray_t *) 190 * Pointer to argument array (previously allocated via 191 * a call to _z_new_args) to free 192 * Returns: void 193 * NOTE: preserves errno (usually called right after e_execCmd*()) 194 */ 195 196 void 197 _z_free_args(argArray_t *a_args) 198 { 199 int i; 200 int lerrno = errno; 201 202 /* entry assertions */ 203 204 assert(a_args != NULL); 205 assert(a_args->_aaArgs != NULL); 206 207 /* free all arguments in the argument array */ 208 209 for (i = (a_args->_aaNumArgs-1); i >= 0; i--) { 210 assert(a_args->_aaArgs[i] != NULL); 211 (void) free(a_args->_aaArgs[i]); 212 } 213 214 /* free argument array */ 215 216 (void) free(a_args->_aaArgs); 217 218 /* free argument array structure */ 219 220 (void) free(a_args); 221 222 /* restore errno */ 223 224 errno = lerrno; 225 } 226 227 /* 228 * Name: _z_get_argc 229 * Description: return (int) argc count from argument array 230 * Arguments: a_args - [RO, *RW] - (argArray_t *) 231 * Pointer to argument array (previously allocated via 232 * a call to _z_new_args) to return argc count for 233 * Returns: int 234 * Count of the number of arguments in the argument array 235 * suitable for use in an exec*() call 236 */ 237 238 int 239 _z_get_argc(argArray_t *a_args) 240 { 241 return (a_args->_aaNumArgs); 242 } 243 244 /* 245 * Name: _z_get_argv 246 * Description: return (char **)argv pointer from argument array 247 * Arguments: a_args - [RO, *RW] - (argArray_t *) 248 * Pointer to argument array (previously allocated via 249 * a call to _z_new_args) to return argv pointer for 250 * Returns: char ** 251 * Pointer to (char **)argv pointer suitable for use 252 * in an exec*() call 253 * NOTE: the actual character array is always terminated with a NULL 254 */ 255 256 char ** 257 _z_get_argv(argArray_t *a_args) 258 { 259 return (a_args->_aaArgs); 260 } 261 262 /* 263 * Name: _z_new_args 264 * Description: create a new argument array for use in exec() calls 265 * Arguments: initialCount - [RO, *RO] - (int) 266 * Initial number of elements to populate the 267 * argument array with - use best guess 268 * Returns: argArray_t * 269 * Pointer to argument array that can be used in other 270 * functions that accept it as an argument 271 * == (argArray_t *)NULL - error 272 * NOTE: you must call _z_free_args() when the returned argument array is 273 * no longer needed so that all storage used can be freed up. 274 */ 275 276 argArray_t * 277 _z_new_args(int initialCount) 278 { 279 argArray_t *aa; 280 281 /* entry assertions */ 282 283 assert(initialCount >= 0); 284 285 /* if no guess on size, then assume 1 */ 286 287 if (initialCount == 0) { 288 initialCount = 1; 289 } 290 291 /* allocate new argument array structure */ 292 293 aa = (argArray_t *)_z_calloc(sizeof (argArray_t)); 294 295 /* allocate initial argument array */ 296 297 aa->_aaArgs = (char **)_z_calloc((initialCount+1) * sizeof (char *)); 298 299 /* initialize argument indexes */ 300 301 aa->_aaNumArgs = 0; 302 aa->_aaMaxArgs = initialCount; 303 304 /* successful - return pointer to argument array created */ 305 306 return (aa); 307 } 308