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
_z_add_arg(argArray_t * a_args,char * a_format,...)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
_z_free_args(argArray_t * a_args)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
_z_get_argc(argArray_t * a_args)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 **
_z_get_argv(argArray_t * a_args)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 *
_z_new_args(int initialCount)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