Home | History | Annotate | Line # | Download | only in global
      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