1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	master_conf 3
6/* SUMMARY
7/*	Postfix master - master.cf file processing
8/* SYNOPSIS
9/*	#include "master.h"
10/*
11/*	void	master_config(serv)
12/*	MASTER_SERV *serv;
13/*
14/*	void	master_refresh(serv)
15/*	MASTER_SERV *serv;
16/* DESCRIPTION
17/*	Use master_config() to read the master.cf configuration file
18/*	during program initialization.
19/*
20/*	Use master_refresh() to re-read the master.cf configuration file
21/*	when the process is already running.
22/* DIAGNOSTICS
23/* BUGS
24/* SEE ALSO
25/*	master_ent(3), configuration file programmatic interface.
26/* LICENSE
27/* .ad
28/* .fi
29/*	The Secure Mailer license must be distributed with this software.
30/* AUTHOR(S)
31/*	Wietse Venema
32/*	IBM T.J. Watson Research
33/*	P.O. Box 704
34/*	Yorktown Heights, NY 10598, USA
35/*--*/
36
37/* System libraries. */
38
39#include <sys_defs.h>
40#include <unistd.h>
41#include <string.h>
42
43/* Utility library. */
44
45#include <msg.h>
46#include <argv.h>
47
48/* Application-specific. */
49
50#include "master.h"
51
52/* master_refresh - re-read configuration table */
53
54void    master_refresh(void)
55{
56    MASTER_SERV *serv;
57    MASTER_SERV **servp;
58
59    /*
60     * Mark all existing services.
61     */
62    for (serv = master_head; serv != 0; serv = serv->next)
63	serv->flags |= MASTER_FLAG_MARK;
64
65    /*
66     * Read the master.cf configuration file. The master_conf() routine
67     * unmarks services upon update. New services are born with the mark bit
68     * off. After this, anything with the mark bit on should be removed.
69     */
70    master_config();
71
72    /*
73     * Delete all services that are still marked - they disappeared from the
74     * configuration file and are therefore no longer needed.
75     */
76    for (servp = &master_head; (serv = *servp) != 0; /* void */ ) {
77	if ((serv->flags & MASTER_FLAG_MARK) != 0) {
78	    *servp = serv->next;
79	    master_stop_service(serv);
80	    free_master_ent(serv);
81	} else {
82	    servp = &serv->next;
83	}
84    }
85}
86
87/* master_config - read config file */
88
89void    master_config(void)
90{
91    MASTER_SERV *entry;
92    MASTER_SERV *serv;
93
94#define STR_DIFF	strcmp
95#define STR_SAME	!strcmp
96#define SWAP(type,a,b)	{ type temp = a; a = b; b = temp; }
97
98    /*
99     * A service is identified by its endpoint name AND by its transport
100     * type, not just by its name alone. The name is unique within its
101     * transport type. XXX Service privacy is encoded in the service name.
102     */
103    set_master_ent();
104    while ((entry = get_master_ent()) != 0) {
105	if (msg_verbose)
106	    print_master_ent(entry);
107	for (serv = master_head; serv != 0; serv = serv->next)
108	    if (STR_SAME(serv->name, entry->name) && serv->type == entry->type)
109		break;
110
111	/*
112	 * Add a new service entry. We do not really care in what order the
113	 * service entries are kept in memory.
114	 */
115	if (serv == 0) {
116	    entry->next = master_head;
117	    master_head = entry;
118	    master_start_service(entry);
119	}
120
121	/*
122	 * Update an existing service entry. Make the current generation of
123	 * child processes commit suicide whenever it is convenient. The next
124	 * generation of child processes will run with the new configuration
125	 * settings.
126	 */
127	else {
128	    serv->flags &= ~MASTER_FLAG_MARK;
129	    if (entry->flags & MASTER_FLAG_CONDWAKE)
130		serv->flags |= MASTER_FLAG_CONDWAKE;
131	    else
132		serv->flags &= ~MASTER_FLAG_CONDWAKE;
133	    serv->wakeup_time = entry->wakeup_time;
134	    serv->max_proc = entry->max_proc;
135	    serv->throttle_delay = entry->throttle_delay;
136	    SWAP(char *, serv->ext_name, entry->ext_name);
137	    SWAP(char *, serv->path, entry->path);
138	    SWAP(ARGV *, serv->args, entry->args);
139	    SWAP(char *, serv->stress_param_val, entry->stress_param_val);
140	    master_restart_service(serv);
141	    free_master_ent(entry);
142	}
143    }
144    end_master_ent();
145}
146