1 /* $NetBSD: postconf_main.c,v 1.1.1.2 2013/09/25 19:06:33 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postconf_main 3 6 /* SUMMARY 7 /* basic support for main.cf 8 /* SYNOPSIS 9 /* #include <postconf.h> 10 /* 11 /* void read_parameters() 12 /* 13 /* void show_parameters(fp, mode, param_class, names) 14 /* VSTREAM *fp; 15 /* int mode; 16 /* int param_class; 17 /* char **names; 18 /* DESCRIPTION 19 /* read_parameters() reads parameters from main.cf. 20 /* 21 /* set_parameters() takes an array of \fIname=value\fR pairs 22 /* and overrides settings read with read_parameters(). 23 /* 24 /* show_parameters() writes main.cf parameters to the specified 25 /* output stream. 26 /* 27 /* Arguments: 28 /* .IP fp 29 /* Output stream. 30 /* .IP mode 31 /* Bit-wise OR of zero or more of the following: 32 /* .RS 33 /* .IP FOLD_LINE 34 /* Fold long lines. 35 /* .IP SHOW_DEFS 36 /* Output default parameter values. 37 /* .IP SHOW_NONDEF 38 /* Output explicit settings only. 39 /* .IP SHOW_NAME 40 /* Output the parameter as "name = value". 41 /* .IP SHOW_EVAL 42 /* Expand $name in parameter values. 43 /* .RE 44 /* .IP param_class 45 /* Bit-wise OR of one or more of the following: 46 /* .RS 47 /* .IP PC_PARAM_FLAG_BUILTIN 48 /* Show built-in parameters. 49 /* .IP PC_PARAM_FLAG_SERVICE 50 /* Show service-defined parameters. 51 /* .IP PC_PARAM_FLAG_USER 52 /* Show user-defined parameters. 53 /* .RE 54 /* .IP names 55 /* List of zero or more parameter names. If the list is empty, 56 /* output all parameters. 57 /* DIAGNOSTICS 58 /* Problems are reported to the standard error stream. 59 /* LICENSE 60 /* .ad 61 /* .fi 62 /* The Secure Mailer license must be distributed with this software. 63 /* AUTHOR(S) 64 /* Wietse Venema 65 /* IBM T.J. Watson Research 66 /* P.O. Box 704 67 /* Yorktown Heights, NY 10598, USA 68 /*--*/ 69 70 /* System library. */ 71 72 #include <sys_defs.h> 73 #include <stdarg.h> 74 #include <stdlib.h> 75 #include <string.h> 76 77 /* Utility library. */ 78 79 #include <msg.h> 80 #include <mymalloc.h> 81 #include <vstream.h> 82 #include <vstring.h> 83 #include <readlline.h> 84 #include <dict.h> 85 #include <stringops.h> 86 #include <htable.h> 87 #include <mac_expand.h> 88 89 /* Global library. */ 90 91 #include <mail_params.h> 92 #include <mail_conf.h> 93 94 /* Application-specific. */ 95 96 #include <postconf.h> 97 98 #define STR(x) vstring_str(x) 99 100 /* read_parameters - read parameter info from file */ 101 102 void read_parameters(void) 103 { 104 char *path; 105 106 /* 107 * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by 108 * better code decomposition. 109 */ 110 set_config_dir(); 111 path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0); 112 if (dict_load_file_xt(CONFIG_DICT, path) == 0) 113 msg_fatal("open %s: %m", path); 114 myfree(path); 115 } 116 117 /* set_parameters - add or override name=value pairs */ 118 119 void set_parameters(char **name_val_array) 120 { 121 char *name, *value, *junk; 122 const char *err; 123 char **cpp; 124 125 for (cpp = name_val_array; *cpp; cpp++) { 126 junk = mystrdup(*cpp); 127 if ((err = split_nameval(junk, &name, &value)) != 0) 128 msg_fatal("invalid parameter override: %s: %s", *cpp, err); 129 mail_conf_update(name, value); 130 myfree(junk); 131 } 132 } 133 134 /* print_line - show line possibly folded, and with normalized whitespace */ 135 136 static void print_line(VSTREAM *fp, int mode, const char *fmt,...) 137 { 138 va_list ap; 139 static VSTRING *buf = 0; 140 char *start; 141 char *next; 142 int line_len = 0; 143 int word_len; 144 145 /* 146 * One-off initialization. 147 */ 148 if (buf == 0) 149 buf = vstring_alloc(100); 150 151 /* 152 * Format the text. 153 */ 154 va_start(ap, fmt); 155 vstring_vsprintf(buf, fmt, ap); 156 va_end(ap); 157 158 /* 159 * Normalize the whitespace. We don't use the line_wrap() routine because 160 * 1) that function does not normalize whitespace between words and 2) we 161 * want to normalize whitespace even when not wrapping lines. 162 * 163 * XXX Some parameters preserve whitespace: for example, smtpd_banner and 164 * smtpd_reject_footer. If we have to preserve whitespace between words, 165 * then perhaps readlline() can be changed to canonicalize whitespace 166 * that follows a newline. 167 */ 168 for (start = STR(buf); *(start += strspn(start, SEPARATORS)) != 0; start = next) { 169 word_len = strcspn(start, SEPARATORS); 170 if (*(next = start + word_len) != 0) 171 *next++ = 0; 172 if (word_len > 0 && line_len > 0) { 173 if ((mode & FOLD_LINE) == 0 || line_len + word_len < LINE_LIMIT) { 174 vstream_fputs(" ", fp); 175 line_len += 1; 176 } else { 177 vstream_fputs("\n" INDENT_TEXT, fp); 178 line_len = INDENT_LEN; 179 } 180 } 181 vstream_fputs(start, fp); 182 line_len += word_len; 183 } 184 vstream_fputs("\n", fp); 185 } 186 187 /* print_parameter - show specific parameter */ 188 189 static void print_parameter(VSTREAM *fp, int mode, const char *name, 190 PC_PARAM_NODE *node) 191 { 192 const char *value; 193 194 /* 195 * Use the default or actual value. 196 */ 197 value = lookup_parameter_value(mode, name, (PC_MASTER_ENT *) 0, node); 198 199 /* 200 * Optionally expand $name in the parameter value. Print the result with 201 * or without the name= prefix. 202 */ 203 if (value != 0) { 204 if ((mode & SHOW_EVAL) != 0 && PC_RAW_PARAMETER(node) == 0) 205 value = expand_parameter_value((VSTRING *) 0, mode, value, 206 (PC_MASTER_ENT *) 0); 207 if (mode & SHOW_NAME) { 208 print_line(fp, mode, "%s = %s\n", name, value); 209 } else { 210 print_line(fp, mode, "%s\n", value); 211 } 212 if (msg_verbose) 213 vstream_fflush(fp); 214 } 215 } 216 217 /* comp_names - qsort helper */ 218 219 static int comp_names(const void *a, const void *b) 220 { 221 PC_PARAM_INFO **ap = (PC_PARAM_INFO **) a; 222 PC_PARAM_INFO **bp = (PC_PARAM_INFO **) b; 223 224 return (strcmp(PC_PARAM_INFO_NAME(ap[0]), 225 PC_PARAM_INFO_NAME(bp[0]))); 226 } 227 228 /* show_parameters - show parameter info */ 229 230 void show_parameters(VSTREAM *fp, int mode, int param_class, char **names) 231 { 232 PC_PARAM_INFO **list; 233 PC_PARAM_INFO **ht; 234 char **namep; 235 PC_PARAM_NODE *node; 236 237 /* 238 * Show all parameters. 239 */ 240 if (*names == 0) { 241 list = PC_PARAM_TABLE_LIST(param_table); 242 qsort((char *) list, param_table->used, sizeof(*list), comp_names); 243 for (ht = list; *ht; ht++) 244 if (param_class & PC_PARAM_INFO_NODE(*ht)->flags) 245 print_parameter(fp, mode, PC_PARAM_INFO_NAME(*ht), 246 PC_PARAM_INFO_NODE(*ht)); 247 myfree((char *) list); 248 return; 249 } 250 251 /* 252 * Show named parameters. 253 */ 254 for (namep = names; *namep; namep++) { 255 if ((node = PC_PARAM_TABLE_FIND(param_table, *namep)) == 0) { 256 msg_warn("%s: unknown parameter", *namep); 257 } else { 258 print_parameter(fp, mode, *namep, node); 259 } 260 } 261 } 262