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