1 /*	$NetBSD: split_nameval.c,v 1.1.1.2 2014/07/06 19:27:58 tron Exp $	*/
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 
split_nameval(char * buf,char ** name,char ** value)63 const 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) do { \
74 	for (var = start; *var && (cond); var++) \
75 	    /* void */; \
76     } while (0)
77 
78 #define TRIM(s) do { \
79 	char *p; \
80 	for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
81 	    /* void */; \
82 	*p = 0; \
83     } while (0)
84 
85     SKIP(buf, np, ISSPACE(*np));		/* find name begin */
86     if (*np == 0)
87 	return ("missing attribute name");
88     SKIP(np, ep, !ISSPACE(*ep) && *ep != '=');	/* find name end */
89     SKIP(ep, cp, ISSPACE(*cp));			/* skip blanks before '=' */
90     if (*cp != '=')				/* need '=' */
91 	return ("missing '=' after attribute name");
92     *ep = 0;					/* terminate name */
93     cp++;					/* skip over '=' */
94     SKIP(cp, vp, ISSPACE(*vp));			/* skip leading blanks */
95     TRIM(vp);					/* trim trailing blanks */
96     *name = np;
97     *value = vp;
98     return (0);
99 }
100