Postfix3.3.1
split_qnameval.c
[詳解]
1 /*++
2 /* NAME
3 /* split_qnameval 3
4 /* SUMMARY
5 /* name-value splitter
6 /* SYNOPSIS
7 /* #include <stringops.h>
8 /*
9 /* const char *split_qnameval(buf, name, value)
10 /* char *buf;
11 /* char **name;
12 /* char **value;
13 /* DESCRIPTION
14 /* split_qnameval() expects text of the form "key = value"
15 /* or "key =", where the key may be quoted with backslash or
16 /* double quotes. The buffer argument is broken up into the key
17 /* and value substrings.
18 /*
19 /* Arguments:
20 /* .IP buf
21 /* Result from readlline() or equivalent. The buffer is modified.
22 /* .IP key
23 /* Upon successful completion, this is set to the key
24 /* substring.
25 /* .IP value
26 /* Upon successful completion, this is set to the value
27 /* substring.
28 /* SEE ALSO
29 /* split_nameval(3) name-value splitter
30 /* BUGS
31 /* DIAGNOSTICS
32 /* The result is a null pointer in case of success, a string
33 /* describing the error otherwise: missing '=' after attribute
34 /* name; missing attribute name.
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /* The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /* Wietse Venema
41 /* Google, Inc.
42 /* 111 8th Avenue
43 /* New York, NY 10011, USA
44 /*--*/
45 
46 /* System libraries. */
47 
48 #include <sys_defs.h>
49 #include <ctype.h>
50 #include <string.h>
51 
52 /* Utility library. */
53 
54 #include <msg.h>
55 #include <stringops.h>
56 
57 /* split_qnameval - split "key = value", support quoted key */
58 
59 const char *split_qnameval(char *buf, char **pkey, char **pvalue)
60 {
61  int in_quotes = 0;
62  char *key;
63  char *key_end;
64  char *value;
65 
66  for (key = buf; *key && ISSPACE(*key); key++)
67  /* void */ ;
68  if (*key == 0)
69  return ("no key found; expected format: key = value");
70 
71  for (key_end = key; *key_end; key_end++) {
72  if (*key_end == '\\') {
73  if (*++key_end == 0)
74  break;
75  } else if (ISSPACE(*key_end) || *key_end == '=') {
76  if (!in_quotes)
77  break;
78  } else if (*key_end == '"') {
79  in_quotes = !in_quotes;
80  }
81  }
82  if (in_quotes) {
83  return ("unbalanced '\"\'");
84  }
85  value = key_end;
86  while (ISSPACE(*value))
87  value++;
88  if (*value != '=')
89  return ("missing '=' after attribute name");
90  *key_end = 0;
91  do {
92  value++;
93  } while (ISSPACE(*value));
94  trimblanks(value, 0)[0] = 0;
95  *pkey = key;
96  *pvalue = value;
97  return (0);
98 }
99 
100 #ifdef TEST
101 
102 #include <stdlib.h>
103 #include <unistd.h>
104 #include <string.h>
105 
106 #include <mymalloc.h>
107 
108 static int compare(int test_number, const char *what,
109  const char *expect, const char *real)
110 {
111  if ((expect == 0 && real == 0)
112  || (expect != 0 && real != 0 && strcmp(expect, real) == 0)) {
113  return (0);
114  } else {
115  msg_warn("test %d: %s mis-match: expect='%s', real='%s'",
116  test_number, what, expect ? expect : "(null)",
117  real ? real : "(null)");
118  return (1);
119  }
120 }
121 
122 int main(int argc, char **argv)
123 {
124  struct test_info {
125  const char *input;
126  const char *expect_result;
127  const char *expect_key;
128  const char *expect_value;
129  };
130  static const struct test_info test_info[] = {
131  /* Unquoted keys. */
132  {"xx = yy", 0, "xx", "yy"},
133  {"xx=yy", 0, "xx", "yy"},
134  {"xx =", 0, "xx", ""},
135  {"xx=", 0, "xx", ""},
136  {"xx", "missing '=' after attribute name", 0, 0},
137  /* Quoted keys. */
138  {"\"xx \" = yy", 0, "\"xx \"", "yy"},
139  {"\"xx \"= yy", 0, "\"xx \"", "yy"},
140  {"\"xx \" =", 0, "\"xx \"", ""},
141  {"\"xx \"=", 0, "\"xx \"", ""},
142  {"\"xx \"", "missing '=' after attribute name", 0, 0},
143  {"\"xx ", "unbalanced '\"'", 0, 0},
144  /* Backslash escapes. */
145  {"\"\\\"xx \" = yy", 0, "\"\\\"xx \"", "yy"},
146  {0,},
147  };
148 
149  int errs = 0;
150  const struct test_info *tp;
151 
152  for (tp = test_info; tp->input != 0; tp++) {
153  const char *result;
154  char *key = 0;
155  char *value = 0;
156  char *buf = mystrdup(tp->input);
157  int test_number = (int) (tp - test_info);
158 
159  result = split_qnameval(buf, &key, &value);
160  errs += compare(test_number, "result", tp->expect_result, result);
161  errs += compare(test_number, "key", tp->expect_key, key);
162  errs += compare(test_number, "value", tp->expect_value, value);
163  myfree(buf);
164  }
165  exit(errs);
166 }
167 
168 #endif
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
int main(int argc, char **argv)
Definition: anvil.c:1010
const char * split_qnameval(char *buf, char **pkey, char **pvalue)
void msg_warn(const char *fmt,...)
Definition: msg.c:215
char ** argv
char * trimblanks(char *, ssize_t)
Definition: trimblanks.c:37
int int
Definition: smtpd_proxy.h:21
#define ISSPACE(c)
Definition: sys_defs.h:1753