1/*	$NetBSD: postconf_service.c,v 1.2 2017/02/14 01:16:46 christos Exp $	*/
2
3/*++
4/* NAME
5/*	postconf_service 3
6/* SUMMARY
7/*	service-defined main.cf parameter name support
8/* SYNOPSIS
9/*	#include <postconf.h>
10/*
11/*	void    pcf_register_service_parameters()
12/* DESCRIPTION
13/*	Service-defined parameter names are created by appending
14/*	postfix-defined suffixes to master.cf service names. All
15/*	service-defined parameters have default values that are
16/*	defined by a built-in parameter.
17/*
18/*	pcf_register_service_parameters() adds the service-defined
19/*	parameters to the global name space. This function must be
20/*	called after the built-in parameters are added to the global
21/*	name space, and after the master.cf file is read.
22/* DIAGNOSTICS
23/*	Problems are reported to the standard error stream.
24/* LICENSE
25/* .ad
26/* .fi
27/*	The Secure Mailer license must be distributed with this software.
28/* AUTHOR(S)
29/*	Wietse Venema
30/*	IBM T.J. Watson Research
31/*	P.O. Box 704
32/*	Yorktown Heights, NY 10598, USA
33/*
34/*	Wietse Venema
35/*	Google, Inc.
36/*	111 8th Avenue
37/*	New York, NY 10011, USA
38/*--*/
39
40/* System library. */
41
42#include <sys_defs.h>
43#include <string.h>
44
45/* Utility library. */
46
47#include <msg.h>
48#include <mymalloc.h>
49#include <htable.h>
50#include <vstring.h>
51#include <stringops.h>
52#include <argv.h>
53
54/* Global library. */
55
56#include <mail_params.h>
57
58/* Application-specific. */
59
60#include <postconf.h>
61
62 /*
63  * Basename of programs in $daemon_directory. XXX These belong in a header
64  * file, or they should be made configurable.
65  */
66#ifndef MAIL_PROGRAM_LOCAL
67#define MAIL_PROGRAM_LOCAL	"local"
68#define MAIL_PROGRAM_ERROR	"error"
69#define MAIL_PROGRAM_VIRTUAL	"virtual"
70#define MAIL_PROGRAM_SMTP	"smtp"
71#define MAIL_PROGRAM_LMTP	"lmtp"
72#define MAIL_PROGRAM_PIPE	"pipe"
73#define MAIL_PROGRAM_SPAWN	"spawn"
74#endif
75
76 /*
77  * Ad-hoc name-value string pair.
78  */
79typedef struct {
80    const char *name;
81    const char *value;
82} PCF_STRING_NV;
83
84#define STR(x) vstring_str(x)
85
86/* pcf_convert_service_parameter - get service parameter string value */
87
88static const char *pcf_convert_service_parameter(void *ptr)
89{
90    return (STR(vstring_sprintf(pcf_param_string_buf, "$%s", (char *) ptr)));
91}
92
93/* pcf_register_service_parameter - add service parameter name and default */
94
95static void pcf_register_service_parameter(const char *service,
96					           const char *suffix,
97					           const char *defparam)
98{
99    char   *name = concatenate(service, suffix, (char *) 0);
100    PCF_PARAM_NODE *node;
101
102    /*
103     * Skip service parameter names that have built-in definitions. This
104     * happens with message delivery transports that have a non-default
105     * per-destination concurrency or recipient limit, such as local(8).
106     *
107     * Some parameters were tentatively flagged as built-in, but they are
108     * service parameters with their own default value. We don't change the
109     * default but we correct the parameter class.
110     */
111    if ((node = PCF_PARAM_TABLE_FIND(pcf_param_table, name)) != 0) {
112	PCF_PARAM_CLASS_OVERRIDE(node, PCF_PARAM_FLAG_SERVICE);
113    } else {
114	PCF_PARAM_TABLE_ENTER(pcf_param_table, name, PCF_PARAM_FLAG_SERVICE,
115			  (void *) defparam, pcf_convert_service_parameter);
116    }
117    myfree(name);
118}
119
120/* pcf_register_service_parameters - add all service parameters with defaults */
121
122void    pcf_register_service_parameters(void)
123{
124    const char *myname = "pcf_register_service_parameters";
125    static const PCF_STRING_NV pipe_params[] = {
126	/* suffix, default parameter name */
127	_MAXTIME, VAR_COMMAND_MAXTIME,
128#define service_params (pipe_params + 1)
129	_XPORT_RCPT_LIMIT, VAR_XPORT_RCPT_LIMIT,
130	_STACK_RCPT_LIMIT, VAR_STACK_RCPT_LIMIT,
131	_XPORT_REFILL_LIMIT, VAR_XPORT_REFILL_LIMIT,
132	_XPORT_REFILL_DELAY, VAR_XPORT_REFILL_DELAY,
133	_DELIVERY_SLOT_COST, VAR_DELIVERY_SLOT_COST,
134	_DELIVERY_SLOT_LOAN, VAR_DELIVERY_SLOT_LOAN,
135	_DELIVERY_SLOT_DISCOUNT, VAR_DELIVERY_SLOT_DISCOUNT,
136	_MIN_DELIVERY_SLOTS, VAR_MIN_DELIVERY_SLOTS,
137	_INIT_DEST_CON, VAR_INIT_DEST_CON,
138	_DEST_CON_LIMIT, VAR_DEST_CON_LIMIT,
139	_DEST_RCPT_LIMIT, VAR_DEST_RCPT_LIMIT,
140	_CONC_POS_FDBACK, VAR_CONC_POS_FDBACK,
141	_CONC_NEG_FDBACK, VAR_CONC_NEG_FDBACK,
142	_CONC_COHORT_LIM, VAR_CONC_COHORT_LIM,
143	_DEST_RATE_DELAY, VAR_DEST_RATE_DELAY,
144	_XPORT_RATE_DELAY, VAR_XPORT_RATE_DELAY,
145	0,
146    };
147    static const PCF_STRING_NV spawn_params[] = {
148	/* suffix, default parameter name */
149	_MAXTIME, VAR_COMMAND_MAXTIME,
150	0,
151    };
152    typedef struct {
153	const char *progname;
154	const PCF_STRING_NV *params;
155    } PCF_SERVICE_DEF;
156    static const PCF_SERVICE_DEF service_defs[] = {
157	MAIL_PROGRAM_LOCAL, service_params,
158	MAIL_PROGRAM_ERROR, service_params,
159	MAIL_PROGRAM_VIRTUAL, service_params,
160	MAIL_PROGRAM_SMTP, service_params,
161	MAIL_PROGRAM_LMTP, service_params,
162	MAIL_PROGRAM_PIPE, pipe_params,
163	MAIL_PROGRAM_SPAWN, spawn_params,
164	0,
165    };
166    const PCF_STRING_NV *sp;
167    const char *progname;
168    const char *service;
169    PCF_MASTER_ENT *masterp;
170    ARGV   *argv;
171    const PCF_SERVICE_DEF *sd;
172
173    /*
174     * Sanity checks.
175     */
176    if (pcf_param_table == 0)
177	msg_panic("%s: global parameter table is not initialized", myname);
178    if (pcf_master_table == 0)
179	msg_panic("%s: master table is not initialized", myname);
180
181    /*
182     * Extract service names from master.cf and generate service parameter
183     * information.
184     */
185    for (masterp = pcf_master_table; (argv = masterp->argv) != 0; masterp++) {
186
187	/*
188	 * Add service parameters for message delivery transports or spawn
189	 * programs.
190	 */
191	progname = argv->argv[7];
192	for (sd = service_defs; sd->progname; sd++) {
193	    if (strcmp(sd->progname, progname) == 0) {
194		service = argv->argv[0];
195		for (sp = sd->params; sp->name; sp++)
196		    pcf_register_service_parameter(service, sp->name, sp->value);
197		break;
198	    }
199	}
200    }
201}
202