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