1 /*        $NetBSD: master_conf.c,v 1.2 2020/03/18 19:05:16 christos Exp $       */
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 /*        Wietse Venema
37 /*        Google, Inc.
38 /*        111 8th Avenue
39 /*        New York, NY 10011, USA
40 /*--*/
41 
42 /* System libraries. */
43 
44 #include <sys_defs.h>
45 #include <unistd.h>
46 #include <string.h>
47 
48 /* Utility library. */
49 
50 #include <msg.h>
51 #include <argv.h>
52 
53 /* Application-specific. */
54 
55 #include "master.h"
56 
57 /* master_refresh - re-read configuration table */
58 
master_refresh(void)59 void    master_refresh(void)
60 {
61     MASTER_SERV *serv;
62     MASTER_SERV **servp;
63 
64     /*
65      * Mark all existing services.
66      */
67     for (serv = master_head; serv != 0; serv = serv->next)
68           serv->flags |= MASTER_FLAG_MARK;
69 
70     /*
71      * Read the master.cf configuration file. The master_conf() routine
72      * unmarks services upon update. New services are born with the mark bit
73      * off. After this, anything with the mark bit on should be removed.
74      */
75     master_config();
76 
77     /*
78      * Delete all services that are still marked - they disappeared from the
79      * configuration file and are therefore no longer needed.
80      */
81     for (servp = &master_head; (serv = *servp) != 0; /* void */ ) {
82           if ((serv->flags & MASTER_FLAG_MARK) != 0) {
83               *servp = serv->next;
84               master_stop_service(serv);
85               free_master_ent(serv);
86           } else {
87               servp = &serv->next;
88           }
89     }
90 }
91 
92 /* master_config - read config file */
93 
master_config(void)94 void    master_config(void)
95 {
96     MASTER_SERV *entry;
97     MASTER_SERV *serv;
98 
99 #define STR_DIFF    strcmp
100 #define STR_SAME    !strcmp
101 #define SWAP(type,a,b)        { type temp = a; a = b; b = temp; }
102 
103     /*
104      * A service is identified by its endpoint name AND by its transport
105      * type, not just by its name alone. The name is unique within its
106      * transport type. XXX Service privacy is encoded in the service name.
107      */
108     set_master_ent();
109     while ((entry = get_master_ent()) != 0) {
110           if (msg_verbose)
111               print_master_ent(entry);
112           for (serv = master_head; serv != 0; serv = serv->next)
113               if (STR_SAME(serv->name, entry->name) && serv->type == entry->type)
114                     break;
115 
116           /*
117            * Add a new service entry. We do not really care in what order the
118            * service entries are kept in memory.
119            */
120           if (serv == 0) {
121               entry->next = master_head;
122               master_head = entry;
123               master_start_service(entry);
124           }
125 
126           /*
127            * Update an existing service entry. Make the current generation of
128            * child processes commit suicide whenever it is convenient. The next
129            * generation of child processes will run with the new configuration
130            * settings.
131            */
132           else {
133               if ((serv->flags & MASTER_FLAG_MARK) == 0)
134                     msg_warn("duplicate master.cf entry for service \"%s\" (%s) "
135                          "-- using the last entry", serv->ext_name, serv->name);
136               else
137                     serv->flags &= ~MASTER_FLAG_MARK;
138               if (entry->flags & MASTER_FLAG_CONDWAKE)
139                     serv->flags |= MASTER_FLAG_CONDWAKE;
140               else
141                     serv->flags &= ~MASTER_FLAG_CONDWAKE;
142               serv->wakeup_time = entry->wakeup_time;
143               serv->max_proc = entry->max_proc;
144               serv->throttle_delay = entry->throttle_delay;
145               SWAP(char *, serv->ext_name, entry->ext_name);
146               SWAP(char *, serv->path, entry->path);
147               SWAP(ARGV *, serv->args, entry->args);
148               SWAP(char *, serv->stress_param_val, entry->stress_param_val);
149               master_restart_service(serv, DO_CONF_RELOAD);
150               free_master_ent(entry);
151           }
152     }
153     end_master_ent();
154 }
155