/*++ /* NAME /* mail_parm_split 3 /* SUMMARY /* split parameter list value /* SYNOPSIS /* #include /* /* ARGV *mail_parm_split( /* const char *name, /* const char *value) /* DESCRIPTION /* mail_parm_split() splits a parameter list value into its /* elements, and extracts text from elements that are entirely /* enclosed in {}. It uses CHARS_COMMA_SP as list element /* delimiters, and CHARS_BRACE for grouping. /* /* Arguments: /* .IP name /* Parameter name. This is used to provide context for /* error messages. /* .IP value /* Parameter value. /* DIAGNOSTICS /* fatal: syntax error while extracting text from {}, such as: /* missing closing brace, or text after closing brace. /* SEE ALSO /* argv_splitq(3), string array utilities /* extpar(3), extract text from parentheses /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* * System library. */ #include /* * Utility library. */ #include #include #include /* * Global library. */ #include #include /* mail_parm_split - split list, extract {text}, errors are fatal */ ARGV *mail_parm_split(const char *name, const char *value) { ARGV *argvp = argv_alloc(1); char *saved_string = mystrdup(value); char *bp = saved_string; char *arg; char *err; /* * The code that detects the error shall either signal or handle the * error. In this case, mystrtokq() detects no error, extpar() signals * the error to its caller, and this function handles the error. */ while ((arg = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { if (*arg == CHARS_BRACE[0] && (err = extpar(&arg, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) { #ifndef TEST msg_fatal("%s: %s", name, err); #else msg_warn("%s: %s", name, err); myfree(err); #endif } argv_add(argvp, arg, (char *) 0); } argv_terminate(argvp); myfree(saved_string); return (argvp); } #ifdef TEST /* * This function is security-critical so it better have a unit-test driver. */ #include #include #include #include int main(void) { VSTRING *vp = vstring_alloc(100); ARGV *argv; char *start; char *str; char **cpp; while (vstring_fgets_nonl(vp, VSTREAM_IN) && VSTRING_LEN(vp) > 0) { start = vstring_str(vp); vstream_printf("Input:\t>%s<\n", start); vstream_fflush(VSTREAM_OUT); argv = mail_parm_split("stdin", start); for (cpp = argv->argv; (str = *cpp) != 0; cpp++) vstream_printf("Output:\t>%s<\n", str); argv_free(argv); vstream_fflush(VSTREAM_OUT); } vstring_free(vp); return (0); } #endif