xref: /onnv-gate/usr/src/lib/libast/common/misc/cmdarg.c (revision 12068:08a39a083754)
18462SApril.Chin@Sun.COM /***********************************************************************
28462SApril.Chin@Sun.COM *                                                                      *
38462SApril.Chin@Sun.COM *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
58462SApril.Chin@Sun.COM *                      and is licensed under the                       *
68462SApril.Chin@Sun.COM *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
88462SApril.Chin@Sun.COM *                                                                      *
98462SApril.Chin@Sun.COM *                A copy of the License is available at                 *
108462SApril.Chin@Sun.COM *            http://www.opensource.org/licenses/cpl1.0.txt             *
118462SApril.Chin@Sun.COM *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
128462SApril.Chin@Sun.COM *                                                                      *
138462SApril.Chin@Sun.COM *              Information and Software Systems Research               *
148462SApril.Chin@Sun.COM *                            AT&T Research                             *
158462SApril.Chin@Sun.COM *                           Florham Park NJ                            *
168462SApril.Chin@Sun.COM *                                                                      *
178462SApril.Chin@Sun.COM *                 Glenn Fowler <gsf@research.att.com>                  *
188462SApril.Chin@Sun.COM *                  David Korn <dgk@research.att.com>                   *
198462SApril.Chin@Sun.COM *                   Phong Vo <kpv@research.att.com>                    *
208462SApril.Chin@Sun.COM *                                                                      *
218462SApril.Chin@Sun.COM ***********************************************************************/
228462SApril.Chin@Sun.COM #pragma prototyped
238462SApril.Chin@Sun.COM /*
248462SApril.Chin@Sun.COM  * Glenn Fowler
258462SApril.Chin@Sun.COM  * AT&T Research
268462SApril.Chin@Sun.COM  *
278462SApril.Chin@Sun.COM  * xargs/tw command arg list support
288462SApril.Chin@Sun.COM  */
298462SApril.Chin@Sun.COM 
308462SApril.Chin@Sun.COM #include <ast.h>
318462SApril.Chin@Sun.COM #include <ctype.h>
328462SApril.Chin@Sun.COM #include <error.h>
338462SApril.Chin@Sun.COM #include <proc.h>
348462SApril.Chin@Sun.COM 
358462SApril.Chin@Sun.COM #include "cmdarg.h"
368462SApril.Chin@Sun.COM 
3710898Sroland.mainz@nrubsig.org #ifndef ARG_MAX
3810898Sroland.mainz@nrubsig.org #define ARG_MAX		(64*1024)
3910898Sroland.mainz@nrubsig.org #endif
408462SApril.Chin@Sun.COM #ifndef EXIT_QUIT
418462SApril.Chin@Sun.COM #define EXIT_QUIT	255
428462SApril.Chin@Sun.COM #endif
438462SApril.Chin@Sun.COM 
448462SApril.Chin@Sun.COM static const char*	echo[] = { "echo", 0 };
458462SApril.Chin@Sun.COM 
468462SApril.Chin@Sun.COM /*
478462SApril.Chin@Sun.COM  * open a cmdarg stream
488462SApril.Chin@Sun.COM  * initialize the command for execution
498462SApril.Chin@Sun.COM  * argv[-1] is reserved for procrun(PROC_ARGMOD)
508462SApril.Chin@Sun.COM  */
518462SApril.Chin@Sun.COM 
528462SApril.Chin@Sun.COM Cmdarg_t*
cmdopen(char ** argv,int argmax,int size,const char * argpat,int flags)538462SApril.Chin@Sun.COM cmdopen(char** argv, int argmax, int size, const char* argpat, int flags)
548462SApril.Chin@Sun.COM {
558462SApril.Chin@Sun.COM 	register Cmdarg_t*	cmd;
568462SApril.Chin@Sun.COM 	register int		n;
578462SApril.Chin@Sun.COM 	register char**		p;
588462SApril.Chin@Sun.COM 	register char*		s;
598462SApril.Chin@Sun.COM 	char*			sh;
608462SApril.Chin@Sun.COM 	int			c;
618462SApril.Chin@Sun.COM 	int			m;
628462SApril.Chin@Sun.COM 	int			argc;
638462SApril.Chin@Sun.COM 	long			x;
648462SApril.Chin@Sun.COM 
658462SApril.Chin@Sun.COM 	char**			post = 0;
668462SApril.Chin@Sun.COM 
678462SApril.Chin@Sun.COM 	n = sizeof(char**);
688462SApril.Chin@Sun.COM 	if (*argv)
698462SApril.Chin@Sun.COM 	{
708462SApril.Chin@Sun.COM 		for (p = argv + 1; *p; p++)
718462SApril.Chin@Sun.COM 		{
728462SApril.Chin@Sun.COM 			if ((flags & CMD_POST) && argpat && streq(*p, argpat))
738462SApril.Chin@Sun.COM 			{
748462SApril.Chin@Sun.COM 				*p = 0;
758462SApril.Chin@Sun.COM 				post = p + 1;
768462SApril.Chin@Sun.COM 				argpat = 0;
778462SApril.Chin@Sun.COM 			}
788462SApril.Chin@Sun.COM 			else
798462SApril.Chin@Sun.COM 				n += strlen(*p) + 1;
808462SApril.Chin@Sun.COM 		}
818462SApril.Chin@Sun.COM 		argc = p - argv;
828462SApril.Chin@Sun.COM 	}
838462SApril.Chin@Sun.COM 	else
848462SApril.Chin@Sun.COM 		argc = 0;
858462SApril.Chin@Sun.COM 	for (p = environ; *p; p++)
868462SApril.Chin@Sun.COM 		n += sizeof(char**) + strlen(*p) + 1;
878462SApril.Chin@Sun.COM 	if ((x = strtol(astconf("ARG_MAX", NiL, NiL), NiL, 0)) <= 0)
888462SApril.Chin@Sun.COM 		x = ARG_MAX;
898462SApril.Chin@Sun.COM 	if (size <= 0 || size > x)
908462SApril.Chin@Sun.COM 		size = x;
918462SApril.Chin@Sun.COM 	sh = pathshell();
928462SApril.Chin@Sun.COM 	m = n + (argc + 4) * sizeof(char**) + strlen(sh) + 1;
938462SApril.Chin@Sun.COM 	m = roundof(m, sizeof(char**));
948462SApril.Chin@Sun.COM 	if (size < m)
958462SApril.Chin@Sun.COM 	{
968462SApril.Chin@Sun.COM 		error(2, "size must be at least %d", m);
978462SApril.Chin@Sun.COM 		return 0;
988462SApril.Chin@Sun.COM 	}
998462SApril.Chin@Sun.COM 	if ((m = x / 10) > 2048)
1008462SApril.Chin@Sun.COM 		m = 2048;
1018462SApril.Chin@Sun.COM 	if (size > (x - m))
1028462SApril.Chin@Sun.COM 		size = x - m;
1038462SApril.Chin@Sun.COM 	n = size - n;
1048462SApril.Chin@Sun.COM 	m = ((flags & CMD_INSERT) && argpat) ? (strlen(argpat) + 1) : 0;
1058462SApril.Chin@Sun.COM 	if (!(cmd = newof(0, Cmdarg_t, 1, n + m)))
1068462SApril.Chin@Sun.COM 	{
1078462SApril.Chin@Sun.COM 		error(ERROR_SYSTEM|2, "out of space");
1088462SApril.Chin@Sun.COM 		return 0;
1098462SApril.Chin@Sun.COM 	}
1108462SApril.Chin@Sun.COM 	c = n / sizeof(char**);
1118462SApril.Chin@Sun.COM 	if (argmax <= 0 || argmax > c)
1128462SApril.Chin@Sun.COM 		argmax = c;
1138462SApril.Chin@Sun.COM 	s = cmd->buf;
1148462SApril.Chin@Sun.COM 	if (!argv[0])
1158462SApril.Chin@Sun.COM 	{
1168462SApril.Chin@Sun.COM 		argv = (char**)echo;
1178462SApril.Chin@Sun.COM 		cmd->echo = 1;
1188462SApril.Chin@Sun.COM 	}
1198462SApril.Chin@Sun.COM 	else if (streq(argv[0], echo[0]))
1208462SApril.Chin@Sun.COM 	{
1218462SApril.Chin@Sun.COM 		cmd->echo = 1;
1228462SApril.Chin@Sun.COM 		flags &= ~CMD_NEWLINE;
1238462SApril.Chin@Sun.COM 	}
1248462SApril.Chin@Sun.COM 	else if (!(flags & CMD_CHECKED))
1258462SApril.Chin@Sun.COM 	{
1268462SApril.Chin@Sun.COM 		if (!pathpath(s, argv[0], NiL, PATH_REGULAR|PATH_EXECUTE))
1278462SApril.Chin@Sun.COM 		{
1288462SApril.Chin@Sun.COM 			if (!(flags & CMD_SILENT))
1298462SApril.Chin@Sun.COM 			{
1308462SApril.Chin@Sun.COM 				error(ERROR_SYSTEM|2, "%s: command not found", argv[0]);
1318462SApril.Chin@Sun.COM 				exit(EXIT_NOTFOUND);
1328462SApril.Chin@Sun.COM 			}
1338462SApril.Chin@Sun.COM 			free(cmd);
1348462SApril.Chin@Sun.COM 			return 0;
1358462SApril.Chin@Sun.COM 		}
1368462SApril.Chin@Sun.COM 		argv[0] = s;
1378462SApril.Chin@Sun.COM 	}
1388462SApril.Chin@Sun.COM 	s += strlen(s) + 1;
1398462SApril.Chin@Sun.COM 	if (m)
1408462SApril.Chin@Sun.COM 	{
1418462SApril.Chin@Sun.COM 		cmd->insert = strcpy(s, argpat);
1428462SApril.Chin@Sun.COM 		cmd->insertlen = m - 1;
1438462SApril.Chin@Sun.COM 		s += m;
1448462SApril.Chin@Sun.COM 	}
1458462SApril.Chin@Sun.COM 	s += sizeof(char**) - (s - cmd->buf) % sizeof(char**);
1468462SApril.Chin@Sun.COM 	p = (char**)s;
1478462SApril.Chin@Sun.COM 	n -= strlen(*p++ = sh) + 1;
1488462SApril.Chin@Sun.COM 	cmd->argv = p;
1498462SApril.Chin@Sun.COM 	while (*p = *argv++)
1508462SApril.Chin@Sun.COM 		p++;
1518462SApril.Chin@Sun.COM 	if (m)
1528462SApril.Chin@Sun.COM 	{
1538462SApril.Chin@Sun.COM 		argmax = 1;
1548462SApril.Chin@Sun.COM 		*p++ = 0;
1558462SApril.Chin@Sun.COM 		cmd->insertarg = p;
1568462SApril.Chin@Sun.COM 		argv = cmd->argv;
1578462SApril.Chin@Sun.COM 		c = *cmd->insert;
1588462SApril.Chin@Sun.COM 		while (s = *argv)
1598462SApril.Chin@Sun.COM 		{
1608462SApril.Chin@Sun.COM 			while ((s = strchr(s, c)) && strncmp(cmd->insert, s, cmd->insertlen))
1618462SApril.Chin@Sun.COM 				s++;
1628462SApril.Chin@Sun.COM 			*p++ = s ? *argv : (char*)0;
1638462SApril.Chin@Sun.COM 			argv++;
1648462SApril.Chin@Sun.COM 		}
1658462SApril.Chin@Sun.COM 		*p++ = 0;
1668462SApril.Chin@Sun.COM 	}
1678462SApril.Chin@Sun.COM 	cmd->firstarg = cmd->nextarg = p;
1688462SApril.Chin@Sun.COM 	cmd->laststr = cmd->nextstr = cmd->buf + n;
1698462SApril.Chin@Sun.COM 	cmd->argmax = argmax;
1708462SApril.Chin@Sun.COM 	cmd->flags = flags;
1718462SApril.Chin@Sun.COM 	cmd->offset = ((cmd->postarg = post) ? (argc - (post - argv)) : 0) + 3;
1728462SApril.Chin@Sun.COM 	return cmd;
1738462SApril.Chin@Sun.COM }
1748462SApril.Chin@Sun.COM 
1758462SApril.Chin@Sun.COM /*
1768462SApril.Chin@Sun.COM  * flush outstanding command file args
1778462SApril.Chin@Sun.COM  */
1788462SApril.Chin@Sun.COM 
1798462SApril.Chin@Sun.COM int
cmdflush(register Cmdarg_t * cmd)1808462SApril.Chin@Sun.COM cmdflush(register Cmdarg_t* cmd)
1818462SApril.Chin@Sun.COM {
1828462SApril.Chin@Sun.COM 	register char*	s;
1838462SApril.Chin@Sun.COM 	register char**	p;
1848462SApril.Chin@Sun.COM 	register int	n;
1858462SApril.Chin@Sun.COM 
1868462SApril.Chin@Sun.COM 	if (cmd->flags & CMD_EMPTY)
1878462SApril.Chin@Sun.COM 		cmd->flags &= ~CMD_EMPTY;
1888462SApril.Chin@Sun.COM 	else if (cmd->nextarg <= cmd->firstarg)
1898462SApril.Chin@Sun.COM 		return 0;
1908462SApril.Chin@Sun.COM 	if ((cmd->flags & CMD_MINIMUM) && cmd->argcount < cmd->argmax)
1918462SApril.Chin@Sun.COM 	{
1928462SApril.Chin@Sun.COM 		if (!(cmd->flags & CMD_SILENT))
1938462SApril.Chin@Sun.COM 			error(2, "%d arg command would be too long", cmd->argcount);
1948462SApril.Chin@Sun.COM 		return -1;
1958462SApril.Chin@Sun.COM 	}
1968462SApril.Chin@Sun.COM 	cmd->total.args += cmd->argcount;
1978462SApril.Chin@Sun.COM 	cmd->total.commands++;
1988462SApril.Chin@Sun.COM 	cmd->argcount = 0;
1998462SApril.Chin@Sun.COM 	if (p = cmd->postarg)
2008462SApril.Chin@Sun.COM 		while (*cmd->nextarg++ = *p++);
2018462SApril.Chin@Sun.COM 	else
2028462SApril.Chin@Sun.COM 		*cmd->nextarg = 0;
2038462SApril.Chin@Sun.COM 	if (s = cmd->insert)
2048462SApril.Chin@Sun.COM 	{
2058462SApril.Chin@Sun.COM 		char*	a;
2068462SApril.Chin@Sun.COM 		char*	b;
2078462SApril.Chin@Sun.COM 		char*	e;
2088462SApril.Chin@Sun.COM 		char*	t;
2098462SApril.Chin@Sun.COM 		char*	u;
2108462SApril.Chin@Sun.COM 		int	c;
2118462SApril.Chin@Sun.COM 		int	m;
2128462SApril.Chin@Sun.COM 
2138462SApril.Chin@Sun.COM 		a = cmd->firstarg[0];
2148462SApril.Chin@Sun.COM 		b = (char*)&cmd->nextarg[1];
2158462SApril.Chin@Sun.COM 		e = cmd->nextstr;
2168462SApril.Chin@Sun.COM 		c = *s;
2178462SApril.Chin@Sun.COM 		m = cmd->insertlen;
2188462SApril.Chin@Sun.COM 		for (n = 1; cmd->argv[n]; n++)
2198462SApril.Chin@Sun.COM 			if (t = cmd->insertarg[n])
2208462SApril.Chin@Sun.COM 			{
2218462SApril.Chin@Sun.COM 				cmd->argv[n] = b;
2228462SApril.Chin@Sun.COM 				for (;;)
2238462SApril.Chin@Sun.COM 				{
2248462SApril.Chin@Sun.COM 					if (!(u = strchr(t, c)))
2258462SApril.Chin@Sun.COM 					{
2268462SApril.Chin@Sun.COM 						b += sfsprintf(b, e - b, "%s", t);
2278462SApril.Chin@Sun.COM 						break;
2288462SApril.Chin@Sun.COM 					}
2298462SApril.Chin@Sun.COM 					if (!strncmp(s, u, m))
2308462SApril.Chin@Sun.COM 					{
2318462SApril.Chin@Sun.COM 						b += sfsprintf(b, e - b, "%-.*s%s", u - t, t, a);
2328462SApril.Chin@Sun.COM 						t = u + m;
2338462SApril.Chin@Sun.COM 					}
2348462SApril.Chin@Sun.COM 					else if (b >= e)
2358462SApril.Chin@Sun.COM 						break;
2368462SApril.Chin@Sun.COM 					else
2378462SApril.Chin@Sun.COM 					{
2388462SApril.Chin@Sun.COM 						*b++ = *u++;
2398462SApril.Chin@Sun.COM 						t = u;
2408462SApril.Chin@Sun.COM 					}
2418462SApril.Chin@Sun.COM 				}
2428462SApril.Chin@Sun.COM 				if (b < e)
2438462SApril.Chin@Sun.COM 					*b++ = 0;
2448462SApril.Chin@Sun.COM 			}
2458462SApril.Chin@Sun.COM 		if (b >= e)
2468462SApril.Chin@Sun.COM 		{
2478462SApril.Chin@Sun.COM 			if (!(cmd->flags & CMD_SILENT))
2488462SApril.Chin@Sun.COM 				error(2, "%s: command too large after insert", a);
2498462SApril.Chin@Sun.COM 			return -1;
2508462SApril.Chin@Sun.COM 		}
2518462SApril.Chin@Sun.COM 	}
2528462SApril.Chin@Sun.COM 	cmd->nextarg = cmd->firstarg;
2538462SApril.Chin@Sun.COM 	cmd->nextstr = cmd->laststr;
2548462SApril.Chin@Sun.COM 	if (cmd->flags & (CMD_QUERY|CMD_TRACE))
2558462SApril.Chin@Sun.COM 	{
2568462SApril.Chin@Sun.COM 		p = cmd->argv;
2578462SApril.Chin@Sun.COM 		sfprintf(sfstderr, "+ %s", *p);
2588462SApril.Chin@Sun.COM 		while (s = *++p)
2598462SApril.Chin@Sun.COM 			sfprintf(sfstderr, " %s", s);
2608462SApril.Chin@Sun.COM 		if (!(cmd->flags & CMD_QUERY))
2618462SApril.Chin@Sun.COM 			sfprintf(sfstderr, "\n");
2628462SApril.Chin@Sun.COM 		else if (astquery(1, "? "))
2638462SApril.Chin@Sun.COM 			return 0;
2648462SApril.Chin@Sun.COM 	}
2658462SApril.Chin@Sun.COM 	if (cmd->echo)
2668462SApril.Chin@Sun.COM 	{
2678462SApril.Chin@Sun.COM 		n = (cmd->flags & CMD_NEWLINE) ? '\n' : ' ';
2688462SApril.Chin@Sun.COM 		for (p = cmd->argv + 1; s = *p++;)
2698462SApril.Chin@Sun.COM 			sfputr(sfstdout, s, *p ? n : '\n');
2708462SApril.Chin@Sun.COM 		n = 0;
2718462SApril.Chin@Sun.COM 	}
2728462SApril.Chin@Sun.COM 	else if ((n = procrun(*cmd->argv, cmd->argv, PROC_ARGMOD|PROC_IGNOREPATH)) == -1)
2738462SApril.Chin@Sun.COM 	{
2748462SApril.Chin@Sun.COM 		if (!(cmd->flags & CMD_SILENT))
2758462SApril.Chin@Sun.COM 		{
2768462SApril.Chin@Sun.COM 			error(ERROR_SYSTEM|2, "%s: command exec error", *cmd->argv);
2778462SApril.Chin@Sun.COM 			exit(EXIT_NOTFOUND - 1);
2788462SApril.Chin@Sun.COM 		}
2798462SApril.Chin@Sun.COM 		return -1;
2808462SApril.Chin@Sun.COM 	}
2818462SApril.Chin@Sun.COM 	else if (n >= EXIT_NOTFOUND - 1)
2828462SApril.Chin@Sun.COM 	{
2838462SApril.Chin@Sun.COM 		if (!(cmd->flags & CMD_SILENT))
2848462SApril.Chin@Sun.COM 			exit(n);
2858462SApril.Chin@Sun.COM 	}
2868462SApril.Chin@Sun.COM 	else if (!(cmd->flags & CMD_IGNORE))
2878462SApril.Chin@Sun.COM 	{
2888462SApril.Chin@Sun.COM 		if (n == EXIT_QUIT && !(cmd->flags & CMD_SILENT))
2898462SApril.Chin@Sun.COM 			exit(2);
2908462SApril.Chin@Sun.COM 		if (n)
2918462SApril.Chin@Sun.COM 			error_info.errors++;
2928462SApril.Chin@Sun.COM 	}
2938462SApril.Chin@Sun.COM 	return n;
2948462SApril.Chin@Sun.COM }
2958462SApril.Chin@Sun.COM 
2968462SApril.Chin@Sun.COM /*
2978462SApril.Chin@Sun.COM  * add file to the command arg list
2988462SApril.Chin@Sun.COM  */
2998462SApril.Chin@Sun.COM 
3008462SApril.Chin@Sun.COM int
cmdarg(register Cmdarg_t * cmd,const char * file,register int len)3018462SApril.Chin@Sun.COM cmdarg(register Cmdarg_t* cmd, const char* file, register int len)
3028462SApril.Chin@Sun.COM {
3038462SApril.Chin@Sun.COM 	int	i;
3048462SApril.Chin@Sun.COM 	int	r;
3058462SApril.Chin@Sun.COM 
3068462SApril.Chin@Sun.COM 	r = 0;
3078462SApril.Chin@Sun.COM 	if (len)
3088462SApril.Chin@Sun.COM 	{
3098462SApril.Chin@Sun.COM 		while ((cmd->nextstr -= len + 1) < (char*)(cmd->nextarg + cmd->offset))
3108462SApril.Chin@Sun.COM 		{
3118462SApril.Chin@Sun.COM 			if (cmd->nextarg == cmd->firstarg)
3128462SApril.Chin@Sun.COM 			{
3138462SApril.Chin@Sun.COM 				error(2, "%s: path too long for exec args", file);
3148462SApril.Chin@Sun.COM 				return -1;
3158462SApril.Chin@Sun.COM 			}
3168462SApril.Chin@Sun.COM 			if (i = cmdflush(cmd))
3178462SApril.Chin@Sun.COM 			{
3188462SApril.Chin@Sun.COM 				if (r < i)
3198462SApril.Chin@Sun.COM 					r = i;
3208462SApril.Chin@Sun.COM 				if (!(cmd->flags & CMD_IGNORE))
3218462SApril.Chin@Sun.COM 					return r;
3228462SApril.Chin@Sun.COM 			}
3238462SApril.Chin@Sun.COM 		}
3248462SApril.Chin@Sun.COM 		*cmd->nextarg++ = cmd->nextstr;
3258462SApril.Chin@Sun.COM 		memcpy(cmd->nextstr, file, len);
3268462SApril.Chin@Sun.COM 		cmd->nextstr[len] = 0;
3278462SApril.Chin@Sun.COM 		cmd->argcount++;
3288462SApril.Chin@Sun.COM 		if (cmd->argcount >= cmd->argmax && (i = cmdflush(cmd)) > r)
3298462SApril.Chin@Sun.COM 			r = i;
3308462SApril.Chin@Sun.COM 	}
3318462SApril.Chin@Sun.COM 	return r;
3328462SApril.Chin@Sun.COM }
3338462SApril.Chin@Sun.COM 
3348462SApril.Chin@Sun.COM /*
3358462SApril.Chin@Sun.COM  * close a cmdarg stream
3368462SApril.Chin@Sun.COM  */
3378462SApril.Chin@Sun.COM 
3388462SApril.Chin@Sun.COM int
cmdclose(Cmdarg_t * cmd)3398462SApril.Chin@Sun.COM cmdclose(Cmdarg_t* cmd)
3408462SApril.Chin@Sun.COM {
3418462SApril.Chin@Sun.COM 	int	n;
3428462SApril.Chin@Sun.COM 
3438462SApril.Chin@Sun.COM 	if ((cmd->flags & CMD_EXACT) && cmd->argcount < cmd->argmax)
3448462SApril.Chin@Sun.COM 	{
3458462SApril.Chin@Sun.COM 		if (!(cmd->flags & CMD_SILENT))
3468462SApril.Chin@Sun.COM 			error(2, "only %d arguments for last command", cmd->argcount);
3478462SApril.Chin@Sun.COM 		return -1;
3488462SApril.Chin@Sun.COM 	}
3498462SApril.Chin@Sun.COM 	cmd->flags &= ~CMD_MINIMUM;
3508462SApril.Chin@Sun.COM 	n = cmdflush(cmd);
3518462SApril.Chin@Sun.COM 	free(cmd);
3528462SApril.Chin@Sun.COM 	return n;
3538462SApril.Chin@Sun.COM }
354