xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/mail_parm_split.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: mail_parm_split.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	mail_parm_split 3
6 /* SUMMARY
7 /*	split parameter list value
8 /* SYNOPSIS
9 /*	#include <mail_parm_split.h>
10 /*
11 /*	ARGV	*mail_parm_split(
12 /*	const char *name,
13 /*	const char *value)
14 /* DESCRIPTION
15 /*	mail_parm_split() splits a parameter list value into its
16 /*	elements, and extracts text from elements that are entirely
17 /*	enclosed in {}. It uses CHARS_COMMA_SP as list element
18 /*	delimiters, and CHARS_BRACE for grouping.
19 /*
20 /*	Arguments:
21 /* .IP name
22 /*	Parameter name. This is used to provide context for
23 /*	error messages.
24 /* .IP value
25 /*	Parameter value.
26 /* DIAGNOSTICS
27 /*	fatal: syntax error while extracting text from {}, such as:
28 /*	missing closing brace, or text after closing brace.
29 /* SEE ALSO
30 /*	argv_splitq(3), string array utilities
31 /*	extpar(3), extract text from parentheses
32 /* LICENSE
33 /* .ad
34 /* .fi
35 /*	The Secure Mailer license must be distributed with this software.
36 /* AUTHOR(S)
37 /*	Wietse Venema
38 /*	IBM T.J. Watson Research
39 /*	P.O. Box 704
40 /*	Yorktown Heights, NY 10598, USA
41 /*--*/
42 
43  /*
44   * System library.
45   */
46 #include <sys_defs.h>
47 
48  /*
49   * Utility library.
50   */
51 #include <msg.h>
52 #include <mymalloc.h>
53 #include <stringops.h>
54 
55  /*
56   * Global library.
57   */
58 #include <mail_params.h>
59 #include <mail_parm_split.h>
60 
61  /*
62   * While testing, do not terminate the program after a syntax error.
63   */
64 #ifdef TEST
65 #undef msg_fatal
66 #define msg_fatal msg_warn
67 #endif
68 
69 /* mail_parm_split - split list, extract {text}, errors are fatal */
70 
71 ARGV   *mail_parm_split(const char *name, const char *value)
72 {
73     ARGV   *argvp = argv_alloc(1);
74     char   *saved_string = mystrdup(value);
75     char   *bp = saved_string;
76     char   *arg;
77     const char *err;
78 
79     /*
80      * The code that detects the error shall either signal or handle the
81      * error. In this case, mystrtokq() detects no error, extpar() signals
82      * the error to its caller, and this function handles the error.
83      */
84     while ((arg = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
85 	if (*arg == CHARS_BRACE[0]
86 	    && (err = extpar(&arg, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0)
87 	    msg_fatal("%s: %s", name, err);
88 	argv_add(argvp, arg, (char *) 0);
89     }
90     argv_terminate(argvp);
91     myfree(saved_string);
92     return (argvp);
93 }
94 
95 #ifdef TEST
96 
97  /*
98   * This function is security-critical so it better have a unit-test driver.
99   */
100 #include <string.h>
101 #include <vstream.h>
102 #include <vstream.h>
103 #include <vstring_vstream.h>
104 
105 int     main(void)
106 {
107     VSTRING *vp = vstring_alloc(100);
108     ARGV   *argv;
109     char   *start;
110     char   *str;
111     char  **cpp;
112 
113     while (vstring_fgets_nonl(vp, VSTREAM_IN) && VSTRING_LEN(vp) > 0) {
114 	start = vstring_str(vp);
115 	vstream_printf("Input:\t>%s<\n", start);
116 	vstream_fflush(VSTREAM_OUT);
117 	argv = mail_parm_split("stdin", start);
118 	for (cpp = argv->argv; (str = *cpp) != 0; cpp++)
119 	    vstream_printf("Output:\t>%s<\n", str);
120 	argv_free(argv);
121 	vstream_fflush(VSTREAM_OUT);
122     }
123     vstring_free(vp);
124     return (0);
125 }
126 
127 #endif
128