/*
 * Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: str2args.c,v 1.6 2007/01/11 17:41:08 ca Exp $")

#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/memops.h"
#include "sm/ctype.h"
#include "sm/rpool.h"
#include "sm/strrcb.h"
#include "sm/str-int.h"
#include "sm/str2rcb.h"

/*
**  SM_STR2ARGS -- split string into argument names and values
**	field1=value SPACE field2=value ...
**	=value is optional, if it doesn't exist argvalues[]=0
**	(it is >0 otherwise). [make it an option whether =value is required?]
**
**	Parameters:
**		str -- string to split
**		offset -- offset at which to start
**		maxargs -- size of argument vectors
**		argnames -- fill in with offsets to argument names
**		argvalues -- fill in with offsets to argument values
**
**	Returns:
**		usual return code
**
**	Side Effects:
**		replaces space and '=' characters in str with '\0'
*/

#define SM_EQUAL	((uchar) '=')

sm_ret_T
sm_str2args(sm_str_P str, uint offset, uint maxargs, uint *argnames, uint *argvalues)
{
	uint i, arg, len;
	uchar c;

	SM_REQUIRE(str != NULL);
	SM_REQUIRE(argnames != NULL);
	SM_REQUIRE(argvalues != NULL);
	SM_REQUIRE(maxargs > 0);

	sm_memzero(argnames, maxargs * sizeof(argnames[0]));
	sm_memzero(argvalues, maxargs * sizeof(argvalues[0]));
	len = sm_str_getlen(str);
	for (i = offset, arg = 0;
	     i < len && (c = sm_str_rd_elem(str, i)) != '\0';
	     i++)
	{
		/* skip over leading spaces */
		while (i < len
		       && (c = sm_str_rd_elem(str, i)) != '\0'
		       && ISSPACE(c))
			++i;
		if (i >= len)
			break;

		/* get name of argument */
		argnames[arg] = i;
		while (i < len
		       && (c = sm_str_rd_elem(str, i)) != '\0'
		       && c != SM_EQUAL
		       && ISPRINT(c) && !ISSPACE(c))
			++i;
		if (i >= len) {
			argvalues[arg] = 0;
			++arg;
			break;
		}
		if (i <= argnames[arg])
			return sm_err_perm(EINVAL);
		if ((c = sm_str_rd_elem(str, i)) != '\0' && SM_EQUAL == c)
			sm_str_wr_elem(str, i, '\0');
		if (SM_EQUAL == c) {
			if (++i >= len)
				return sm_err_perm(EINVAL);

			/* get name of argument */
			argvalues[arg] = i;
			while (i < len
			       && (c = sm_str_rd_elem(str, i)) != '\0'
			       && ISPRINT(c) && !ISSPACE(c))
				++i;
			if (i <= argvalues[arg])
				return sm_err_perm(EINVAL);
		}
		else
			argvalues[arg] = 0;
		++arg;
		if (i >= len)
			break;

		if ((c = sm_str_rd_elem(str, i)) != '\0') {
			if (ISSPACE(c))
				sm_str_wr_elem(str, i, '\0');
			else
				return sm_err_perm(EINVAL);
		}

		if (arg >= maxargs)
			return sm_err_perm(E2BIG);
	}
	return arg;
}


syntax highlighted by Code2HTML, v. 0.9.1