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 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 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