]> git.pond.sub.org Git - empserver/blob - src/lib/common/wantupd.c
Indented with src/scripts/indent-emp.
[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 "keyword.h"
42 #include "wantupd.h"
43 #include "optlist.h"
44 #include "common.h"
45
46 #include <sys/types.h>
47 #include <fcntl.h>
48 #if defined(Rel4) || defined(_WIN32)
49 #include <time.h>
50 #else  /* Rel4 */
51 #include <sys/time.h>
52 #endif /* Rel4 */
53
54 void
55 update_policy_check(void)
56 {
57     extern int update_policy, update_demandpolicy;
58     extern int update_wantmin, blitz_time;
59
60     if (update_policy < 0)
61         update_policy = UDP_DEFAULT;
62     if (update_policy > UDP_MAX)
63         update_policy = UDP_DEFAULT;
64     if (update_demandpolicy < 0)
65         update_demandpolicy = UDDEM_DEFAULT;
66     if (update_demandpolicy > UDDEM_MAX)
67         update_demandpolicy = UDDEM_DEFAULT;
68     if (update_wantmin < 0)
69         update_wantmin = 0;
70     if (update_wantmin > MAXNOC)
71         update_wantmin = MAXNOC;
72     if (blitz_time < 0)
73         blitz_time = 0;
74 }
75
76 static int
77 demand_update_time(time_t * now)
78 {
79     struct tm *tm;
80     s_char *p;
81     int curtime;
82     int hour[2];
83     extern s_char *update_demandtimes;
84
85     tm = localtime(now);
86     curtime = tm->tm_min + tm->tm_hour * 60;
87     p = update_demandtimes;
88     if (*p == 0)
89         return (1);
90     while (NULL != (p = kw_parse(CF_TIMERANGE, p, &hour[0]))) {
91         if (curtime >= hour[0] && curtime < hour[1])
92             return (1);
93     }
94     return (0);
95 }
96
97 /* When is the next regularly scheduled update from now. */
98 static void
99 regular_update_time(time_t * now, time_t * tim, time_t * delta)
100 {
101     extern int s_p_etu;
102     extern int etu_per_update;
103     extern int adj_update;
104     s_char *p;
105     time_t tw;
106     int secs_per_update;
107
108     tw = *now + adj_update;
109     secs_per_update = etu_per_update * s_p_etu;
110     *delta = secs_per_update - (tw % secs_per_update);
111     *tim = *now + *delta;
112 }
113
114 /* Is this a valid time for a scheduled update. */
115 static int
116 scheduled_update_time(time_t * now, int *which)
117 {
118     struct tm *tm;
119     s_char *p, *p1;
120     int curtime;
121     int hour;
122     extern int hourslop;
123     extern s_char *update_times;
124
125     *which = -1;
126     p = update_times;
127     if (*p == 0)
128         return (0);
129
130     tm = localtime(now);
131     curtime = tm->tm_min + tm->tm_hour * 60;
132     while (NULL != (p = kw_parse(CF_TIME, p, &hour))) {
133         (*which)++;
134         if (curtime >= hour && curtime < hour + hourslop)
135             return (1);
136     }
137
138     return 0;
139 }
140
141 static int
142 next_scheduled_time(time_t * now, time_t * tim, time_t * delta)
143 {
144     struct tm *tm;
145     s_char *p;
146     int curtime;
147     int hour;
148     int mintime;
149     extern s_char *update_times;
150
151     p = update_times;
152     if (*p == 0)
153         return (0);
154
155     tm = localtime(now);
156     curtime = tm->tm_min + tm->tm_hour * 60;    /* now - in minutes */
157     mintime = curtime + 24 * 60 + 1;    /* start with now + 1 day */
158     while (NULL != (p = kw_parse(CF_TIME, p, &hour))) {
159         if (hour <= curtime)
160             hour += 24 * 60;    /* this must be tomorrow */
161         if (hour < mintime)
162             mintime = hour;     /* this is best bet so far */
163     }
164     *delta = 60 * (mintime - curtime);
165     *tim = *now + *delta - tm->tm_sec;
166     return (1);
167 }
168
169 int
170 demand_update_want(int *want, int *pop, int which)
171 {
172     natid cn;
173     struct natstr *natp;
174     int totpop;
175     int totwant;
176     int whichwants;
177
178     whichwants = totpop = totwant = 0;
179     for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
180         /* Only countries which are normal. */
181         /* Should probably include sanctuaries ..... */
182         if (((natp->nat_stat & NORM) == NORM) &&
183             ((natp->nat_stat & GOD) != GOD)) {
184             totpop++;
185             if ((natp->nat_update & WUPD_WANT) == WUPD_WANT) {
186                 totwant++;
187                 if (which == cn)
188                     whichwants++;
189             }
190         }
191     }
192     *want = totwant;
193     *pop = totpop;
194     return (whichwants);
195 }
196
197 static int
198 demand_check(void)
199 {
200     extern int update_wantmin, update_missed;
201     struct natstr *natp;
202     int want, pop, cn, veto;
203     time_t now;
204     time_t cur;
205     extern long last_demand_update;
206
207     time(&cur);
208
209 /*
210         if (last_demand_update == 0){
211                 natp=getnatp(0);
212                 last_demand_update = natp->nat_reserve;
213         }
214
215         logerror("last_demand_update = %d\n",last_demand_update);
216         logerror("update_between = %d\n",update_between());
217         logerror("now = %d\n",cur);
218         diff = (cur-(last_demand_update + update_between()));
219         logerror("diff = %d\n",diff);
220         if (diff >= 0){
221                 logerror("Forced update!\n");
222                 last_demand_update = cur;
223                 for (cn = 1; natp = getnatp(cn); cn++){
224                         if (((natp->nat_stat & NORM) == NORM)  &&
225                                 ((natp->nat_stat & GOD) != GOD)){
226                                 natp->nat_missed = 0;
227                         }
228                 }
229                 return(1);
230         }
231
232         logerror("No forced update!\n");
233 */
234     if (0 == update_wantmin) {
235         logerror("no demand update allowed, wantmin = 0");
236         return (0);
237     }
238
239     demand_update_want(&want, &pop, 0);
240     if (want < update_wantmin) {
241         logerror("no demand update, want = %d, min = %d",
242                  want, update_wantmin);
243         return (0);
244     }
245
246     time(&now);
247     if (!demand_update_time(&now)) {
248         logerror("no demand update, not within hours allowed.");
249         return (0);
250     }
251
252
253     veto = 0;
254     for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
255         if (((natp->nat_stat & NORM) == NORM) &&
256             ((natp->nat_stat & GOD) != GOD)) {
257             if (natp->nat_missed >= update_missed)
258                 veto = cn + 1;
259         }
260     }
261
262     if (veto) {
263         logerror("no demand update, %d has missed more than %d updates",
264                  veto - 1, update_missed);
265         return (0);
266     }
267
268     last_demand_update = cur;
269     natp = getnatp(0);
270     /* A dumb way to do it, but simple */
271     last_demand_update = natp->nat_reserve;
272     return (1);
273 }
274
275 /* Check if enough countries want an update,
276  * and if demand updates are allowed now.
277  */
278 int
279 demandupdatecheck(void)
280 {
281     extern int update_demandpolicy;
282
283     if (UDDEM_COMSET != update_demandpolicy) {
284         logerror("no demand update, not policy.");
285         return (0);
286     }
287
288     return (demand_check());
289 }
290
291 /* Is it time for a regular or scheduled update?
292  * As well, if none of the above, check to see if
293  * a demand update can occur.
294  */
295 int
296 updatetime(time_t * now)
297 {
298     extern int update_policy;
299     int which;
300
301     if (opt_BLITZ && update_policy == UDP_BLITZ) {
302         logerror("BLITZ Update.");
303         return (1);
304     }
305
306     if (UDP_NORMAL == update_policy) {
307         logerror("Regular update, etu type.");
308         return (1);
309     }
310
311     if (UDP_TIMES == update_policy) {
312         if (scheduled_update_time(now, &which)) {
313             logerror("Scheduled update, %d.", which);
314             return (1);
315         }
316     }
317     if (opt_DEMANDUPDATE) {
318         if (demand_check()) {
319             logerror("Demand update, at check time.");
320             return (1);
321         }
322     }
323     return (0);
324 }
325
326 /* Return the time, and delta seconds, of the next update.
327  * If the policy is no regular updates, return the time of
328  * the next possible check.
329  */
330 void
331 next_update_time(time_t * now, time_t * tim, time_t * delta)
332                         /* From when */
333                         /* Time of next update */
334                         /* Seconds till next update */
335 {
336     extern int update_policy;
337     time_t stim, sdelta;
338     extern int blitz_time;
339
340     switch (update_policy) {
341     case UDP_NORMAL:
342         regular_update_time(now, tim, delta);
343         break;
344     case UDP_TIMES:
345         if (!next_scheduled_time(now, tim, delta))
346             regular_update_time(now, tim, delta);
347         break;
348     case UDP_BLITZ:
349         *delta = (blitz_time * 60) - (*now % (blitz_time * 60));
350         *tim = *now + *delta;
351         break;
352
353     case UDP_NOREG:
354     default:
355         regular_update_time(now, tim, delta);
356         if (next_scheduled_time(now, &stim, &sdelta)) {
357             if (*delta > sdelta) {
358                 *delta = sdelta;
359                 *tim = stim;
360             }
361         }
362         break;
363     }
364 }
365
366 void
367 next_update_check_time(time_t * now, time_t * tim, time_t * delta)
368                         /* From when */
369                         /* Time of next update */
370                         /* Seconds till next update check */
371 {
372     extern int update_policy;
373     time_t stim, sdelta;
374     extern int blitz_time;
375
376     switch (update_policy) {
377     case UDP_NORMAL:
378         regular_update_time(now, tim, delta);
379         break;
380     case UDP_BLITZ:
381         *delta = (blitz_time * 60) - (*now % (blitz_time * 60));
382         *tim = *now + *delta;
383         break;
384     case UDP_TIMES:
385     case UDP_NOREG:
386     default:
387         regular_update_time(now, tim, delta);
388         if (next_scheduled_time(now, &stim, &sdelta)) {
389             if (*delta > sdelta) {
390                 *delta = sdelta;
391                 *tim = stim;
392             }
393         }
394     }
395 }
396
397 int
398 updates_disabled(void)
399 {
400     extern s_char *disablefil;
401     int fd;
402
403     if ((fd = open(disablefil, O_RDONLY, 0)) < 0)
404         return 0;
405     close(fd);
406     return 1;
407 }