]> git.pond.sub.org Git - empserver/blob - src/lib/common/wantupd.c
(weekday, daytime, daytime_range): New; replace kw_parse(). Parsing
[empserver] / src / lib / common / wantupd.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  wantupd.c: Check to se if an update is wanted and/or allowed.
29  * 
30  *  Known contributors to this file:
31  *     Doug Hay, 1990
32  */
33
34 #include <stdio.h>
35 #if !defined(_WIN32)
36 #include <unistd.h>
37 #endif
38 #include "misc.h"
39 #include "nat.h"
40 #include "file.h"
41 #include "wantupd.h"
42 #include "optlist.h"
43 #include "common.h"
44
45 #include <sys/types.h>
46 #include <fcntl.h>
47 #include <time.h>
48
49 void
50 update_policy_check(void)
51 {
52     if (update_policy < 0)
53         update_policy = UDP_DEFAULT;
54     if (update_policy > UDP_MAX)
55         update_policy = UDP_DEFAULT;
56     if (update_demandpolicy < 0)
57         update_demandpolicy = UDDEM_DEFAULT;
58     if (update_demandpolicy > UDDEM_MAX)
59         update_demandpolicy = UDDEM_DEFAULT;
60     if (update_wantmin < 0)
61         update_wantmin = 0;
62     if (update_wantmin > MAXNOC)
63         update_wantmin = MAXNOC;
64     if (blitz_time < 0)
65         blitz_time = 0;
66 }
67
68 static int
69 demand_update_time(time_t *now)
70 {
71     struct tm *tm;
72
73     tm = localtime(now);
74     return is_daytime_allowed(60 * tm->tm_hour + tm->tm_min,
75                               update_demandtimes);
76 }
77
78 /* When is the next regularly scheduled update from now. */
79 static void
80 regular_update_time(time_t *now, time_t *tim, time_t *delta)
81 {
82     time_t tw;
83     int secs_per_update;
84
85     tw = *now + adj_update;
86     secs_per_update = etu_per_update * s_p_etu;
87     *delta = secs_per_update - (tw % secs_per_update);
88     *tim = *now + *delta;
89 }
90
91 /* Is this a valid time for a scheduled update. */
92 static int
93 scheduled_update_time(time_t *now)
94 {
95     struct tm *tm;
96
97     tm = localtime(now);
98     return is_daytime_near(60 * tm->tm_hour + tm->tm_min,
99                            update_times, hourslop);
100 }
101
102 static int
103 next_scheduled_time(time_t *now, time_t *tim, time_t *delta)
104 {
105     struct tm *tm;
106     int d;
107
108     tm = localtime(now);
109     d = min_to_next_daytime(60 * tm->tm_hour + tm->tm_min, update_times);
110     if (d < 0)
111         return 0;
112     *delta = 60 * d;
113     *tim = *now + *delta - tm->tm_sec;
114     return 1;
115 }
116
117 int
118 demand_update_want(int *want, int *pop, int which)
119 {
120     natid cn;
121     struct natstr *natp;
122     int totpop;
123     int totwant;
124     int whichwants;
125
126     whichwants = totpop = totwant = 0;
127     for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
128         /* Only countries which are normal. */
129         /* Should probably include sanctuaries ..... */
130         if (((natp->nat_stat & NORM) == NORM) &&
131             ((natp->nat_stat & GOD) != GOD)) {
132             totpop++;
133             if ((natp->nat_update & WUPD_WANT) == WUPD_WANT) {
134                 totwant++;
135                 if (which == cn)
136                     whichwants++;
137             }
138         }
139     }
140     *want = totwant;
141     *pop = totpop;
142     return (whichwants);
143 }
144
145 static int
146 demand_check(void)
147 {
148     struct natstr *natp;
149     int want, pop, cn, veto;
150     time_t now;
151     time_t cur;
152
153     time(&cur);
154
155 /*
156         if (last_demand_update == 0){
157                 natp=getnatp(0);
158                 last_demand_update = natp->nat_reserve;
159         }
160
161         logerror("last_demand_update = %d\n",last_demand_update);
162         logerror("update_between = %d\n",update_between());
163         logerror("now = %d\n",cur);
164         diff = (cur-(last_demand_update + update_between()));
165         logerror("diff = %d\n",diff);
166         if (diff >= 0){
167                 logerror("Forced update!\n");
168                 last_demand_update = cur;
169                 for (cn = 1; natp = getnatp(cn); cn++){
170                         if (((natp->nat_stat & NORM) == NORM)  &&
171                                 ((natp->nat_stat & GOD) != GOD)){
172                                 natp->nat_missed = 0;
173                         }
174                 }
175                 return(1);
176         }
177
178         logerror("No forced update!\n");
179 */
180     if (0 == update_wantmin) {
181         logerror("no demand update allowed, wantmin = 0");
182         return (0);
183     }
184
185     demand_update_want(&want, &pop, 0);
186     if (want < update_wantmin) {
187         logerror("no demand update, want = %d, min = %d",
188                  want, update_wantmin);
189         return (0);
190     }
191
192     time(&now);
193     if (!demand_update_time(&now)) {
194         logerror("no demand update, not within hours allowed.");
195         return (0);
196     }
197
198
199     veto = 0;
200     for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
201         if (((natp->nat_stat & NORM) == NORM) &&
202             ((natp->nat_stat & GOD) != GOD)) {
203             if (natp->nat_missed >= update_missed)
204                 veto = cn + 1;
205         }
206     }
207
208     if (veto) {
209         logerror("no demand update, %d has missed more than %d updates",
210                  veto - 1, update_missed);
211         return (0);
212     }
213
214     last_demand_update = cur;
215     natp = getnatp(0);
216     /* A dumb way to do it, but simple */
217     last_demand_update = natp->nat_reserve;
218     return (1);
219 }
220
221 /* Check if enough countries want an update,
222  * and if demand updates are allowed now.
223  */
224 int
225 demandupdatecheck(void)
226 {
227     if (UDDEM_COMSET != update_demandpolicy) {
228         logerror("no demand update, not policy.");
229         return (0);
230     }
231
232     return (demand_check());
233 }
234
235 /* Is it time for a regular or scheduled update?
236  * As well, if none of the above, check to see if
237  * a demand update can occur.
238  */
239 int
240 updatetime(time_t *now)
241 {
242     if (opt_BLITZ && update_policy == UDP_BLITZ) {
243         logerror("BLITZ Update.");
244         return (1);
245     }
246
247     if (UDP_NORMAL == update_policy) {
248         logerror("Regular update, etu type.");
249         return (1);
250     }
251
252     if (UDP_TIMES == update_policy) {
253         if (scheduled_update_time(now)) {
254             logerror("Scheduled update.");
255             return (1);
256         }
257     }
258     if (opt_DEMANDUPDATE) {
259         if (demand_check()) {
260             logerror("Demand update, at check time.");
261             return (1);
262         }
263     }
264     return (0);
265 }
266
267 /* Return the time, and delta seconds, of the next update.
268  * If the policy is no regular updates, return the time of
269  * the next possible check.
270  */
271 void
272 next_update_time(time_t *now, time_t *tim, time_t *delta)
273                         /* From when */
274                         /* Time of next update */
275                         /* Seconds till next update */
276 {
277     time_t stim, sdelta;
278
279     switch (update_policy) {
280     case UDP_NORMAL:
281         regular_update_time(now, tim, delta);
282         break;
283     case UDP_TIMES:
284         if (!next_scheduled_time(now, tim, delta))
285             regular_update_time(now, tim, delta);
286         break;
287     case UDP_BLITZ:
288         *delta = (blitz_time * 60) - (*now % (blitz_time * 60));
289         *tim = *now + *delta;
290         break;
291
292     case UDP_NOREG:
293     default:
294         regular_update_time(now, tim, delta);
295         if (next_scheduled_time(now, &stim, &sdelta)) {
296             if (*delta > sdelta) {
297                 *delta = sdelta;
298                 *tim = stim;
299             }
300         }
301         break;
302     }
303 }
304
305 void
306 next_update_check_time(time_t *now, time_t *tim, time_t *delta)
307                         /* From when */
308                         /* Time of next update */
309                         /* Seconds till next update check */
310 {
311     time_t stim, sdelta;
312
313     switch (update_policy) {
314     case UDP_NORMAL:
315         regular_update_time(now, tim, delta);
316         break;
317     case UDP_BLITZ:
318         *delta = (blitz_time * 60) - (*now % (blitz_time * 60));
319         *tim = *now + *delta;
320         break;
321     case UDP_TIMES:
322     case UDP_NOREG:
323     default:
324         regular_update_time(now, tim, delta);
325         if (next_scheduled_time(now, &stim, &sdelta)) {
326             if (*delta > sdelta) {
327                 *delta = sdelta;
328                 *tim = stim;
329             }
330         }
331     }
332 }
333
334 int
335 updates_disabled(void)
336 {
337     int fd;
338
339     if ((fd = open(disablefil, O_RDONLY, 0)) < 0)
340         return 0;
341     close(fd);
342     return 1;
343 }