1 /* $NetBSD: mail_parm_split.c,v 1.3 2020/03/18 19:05:16 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 /* Wietse Venema
43 /* Google, Inc.
44 /* 111 8th Avenue
45 /* New York, NY 10011, USA
46 /*--*/
47
48 /*
49 * System library.
50 */
51 #include <sys_defs.h>
52
53 /*
54 * Utility library.
55 */
56 #include <msg.h>
57 #include <mymalloc.h>
58 #include <stringops.h>
59
60 /*
61 * Global library.
62 */
63 #include <mail_params.h>
64 #include <mail_parm_split.h>
65
66 /* mail_parm_split - split list, extract {text}, errors are fatal */
67
mail_parm_split(const char * name,const char * value)68 ARGV *mail_parm_split(const char *name, const char *value)
69 {
70 ARGV *argvp = argv_alloc(1);
71 char *saved_string = mystrdup(value);
72 char *bp = saved_string;
73 char *arg;
74 char *err;
75
76 /*
77 * The code that detects the error shall either signal or handle the
78 * error. In this case, mystrtokq() detects no error, extpar() signals
79 * the error to its caller, and this function handles the error.
80 */
81 while ((arg = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
82 if (*arg == CHARS_BRACE[0]
83 && (err = extpar(&arg, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) {
84 #ifndef TEST
85 msg_fatal("%s: %s", name, err);
86 #else
87 msg_warn("%s: %s", name, err);
88 myfree(err);
89 #endif
90 }
91 argv_add(argvp, arg, (char *) 0);
92 }
93 argv_terminate(argvp);
94 myfree(saved_string);
95 return (argvp);
96 }
97
98 #ifdef TEST
99
100 /*
101 * This function is security-critical so it better have a unit-test driver.
102 */
103 #include <string.h>
104 #include <vstream.h>
105 #include <vstream.h>
106 #include <vstring_vstream.h>
107
main(void)108 int main(void)
109 {
110 VSTRING *vp = vstring_alloc(100);
111 ARGV *argv;
112 char *start;
113 char *str;
114 char **cpp;
115
116 while (vstring_fgets_nonl(vp, VSTREAM_IN) && VSTRING_LEN(vp) > 0) {
117 start = vstring_str(vp);
118 vstream_printf("Input:\t>%s<\n", start);
119 vstream_fflush(VSTREAM_OUT);
120 argv = mail_parm_split("stdin", start);
121 for (cpp = argv->argv; (str = *cpp) != 0; cpp++)
122 vstream_printf("Output:\t>%s<\n", str);
123 argv_free(argv);
124 vstream_fflush(VSTREAM_OUT);
125 }
126 vstring_free(vp);
127 return (0);
128 }
129
130 #endif
131