1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	split_nameval 3
6/* SUMMARY
7/*	name-value splitter
8/* SYNOPSIS
9/*	#include <split_nameval.h>
10/*
11/*	const char *split_nameval(buf, name, value)
12/*	char	*buf;
13/*	char	**name;
14/*	char	**value;
15/* DESCRIPTION
16/*	split_nameval() takes a logical line from readlline() and expects
17/*	text of the form "name = value" or "name =". The buffer
18/*	argument is broken up into name and value substrings.
19/*
20/*	Arguments:
21/* .IP buf
22/*	Result from readlline() or equivalent. The buffer is modified.
23/* .IP name
24/*	Upon successful completion, this is set to the name
25/*	substring.
26/* .IP value
27/*	Upon successful completion, this is set to the value
28/*	substring.
29/* FEATURES
30/* SEE ALSO
31/*	dict(3) mid-level dictionary routines
32/* BUGS
33/* DIAGNOSTICS
34/*	Fatal errors: out of memory.
35/*
36/*	The result is a null pointer in case of success, a string
37/*	describing the error otherwise: missing '=' after attribute
38/*	name; missing attribute name.
39/* LICENSE
40/* .ad
41/* .fi
42/*	The Secure Mailer license must be distributed with this software.
43/* AUTHOR(S)
44/*	Wietse Venema
45/*	IBM T.J. Watson Research
46/*	P.O. Box 704
47/*	Yorktown Heights, NY 10598, USA
48/*--*/
49
50/* System libraries. */
51
52#include "sys_defs.h"
53#include <ctype.h>
54#include <string.h>
55
56/* Utility library. */
57
58#include <msg.h>
59#include <stringops.h>
60
61/* split_nameval - split text into name and value */
62
63const char *split_nameval(char *buf, char **name, char **value)
64{
65    char   *np;				/* name substring */
66    char   *vp;				/* value substring */
67    char   *cp;
68    char   *ep;
69
70    /*
71     * Ugly macros to make complex expressions less unreadable.
72     */
73#define SKIP(start, var, cond) \
74	for (var = start; *var && (cond); var++);
75
76#define TRIM(s) { \
77	char *p; \
78	for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
79	*p = 0; \
80    }
81
82    SKIP(buf, np, ISSPACE(*np));		/* find name begin */
83    if (*np == 0)
84	return ("missing attribute name");
85    SKIP(np, ep, !ISSPACE(*ep) && *ep != '=');	/* find name end */
86    SKIP(ep, cp, ISSPACE(*cp));			/* skip blanks before '=' */
87    if (*cp != '=')				/* need '=' */
88	return ("missing '=' after attribute name");
89    *ep = 0;					/* terminate name */
90    cp++;					/* skip over '=' */
91    SKIP(cp, vp, ISSPACE(*vp));			/* skip leading blanks */
92    TRIM(vp);					/* trim trailing blanks */
93    *name = np;
94    *value = vp;
95    return (0);
96}
97