source: trunk/src/sh_schedule.c@ 6

Last change on this file since 6 was 1, checked in by katerina, 19 years ago

Initial import

File size: 9.0 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2002 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26
27#include <errno.h>
28#include <sys/types.h>
29#include <unistd.h>
30
31/*
32 gcc -Wall -O2 -o mysched sh_schedule.c -DTESTONLY
33 */
34#ifndef TESTONLY
35
36
37#undef FIL__
38#define FIL__ _("sh_schedule.c")
39
40#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
41#define SCHEDULER_YES
42#endif
43
44#if TIME_WITH_SYS_TIME
45#include <sys/time.h>
46#include <time.h>
47#else
48#if HAVE_SYS_TIME_H
49#include <sys/time.h>
50#else
51#include <time.h>
52#endif
53#endif
54
55#include "sh_mem.h"
56
57/* TESTONLY */
58#else
59
60#define SCHEDULER_YES
61#include <time.h>
62
63#endif
64
65#include "sh_schedule.h"
66
67
68
69#ifdef SCHEDULER_YES
70
71/************************************************
72 *
73 * Scheduler class - private area
74 *
75 ************************************************/
76
77
78static const int sh_schedule_max[5] = { 59, 23, 31, 12, 7 };
79static const int sh_schedule_min[5] = { 0, 0, 0, 0, 0 };
80
81static
82int test_val (int i, int min, int max, int min_step,
83 time_t * last, time_t now, int nval, int first_flag)
84{
85 /* don't miss a minute's task
86 * IDEA: set last = now after first check (? seems to work)
87 */
88 if (i == 0 && max == min && nval > max
89 /* && ( ((now - *last) > min_step) || (*last == (time_t)-1) ) */ )
90 {
91 if (*last == (time_t)-1)
92 {
93 /* fake execution at nval-max
94 */
95 *last = now - 60 * (nval-max);
96 return 0;
97 }
98 if ((int)(now - *last) > min_step)
99 return 1;
100 }
101
102 /* out of range
103 */
104 if (nval > max || nval < min)
105 return 0;
106
107 /* first call - invalid last_exec
108
109 if (*last == (time_t)-1)
110 return 1;
111 */
112
113 if (first_flag == 0)
114 return 1;
115
116
117 /* before min_step - too early (e.g. same minute)
118 */
119 if ((int)(now - *last) <= min_step)
120 return 0;
121
122 return 1;
123}
124
125static
126int test_sched_int (sh_schedule_t * isched)
127{
128 time_t now;
129 struct tm * tval;
130 int count, i, nval;
131
132 if (!isched)
133 return 0;
134
135 now = time(NULL);
136 tval = localtime(&now);
137
138 count = 0;
139 for (i = 0; i < 5; ++i)
140 {
141 if (i == 0) nval = tval->tm_min;
142 else if (i == 1) nval = tval->tm_hour;
143 else if (i == 2) nval = tval->tm_mday;
144 else if (i == 3) nval = tval->tm_mon;
145 else nval = tval->tm_wday;
146 count += test_val (i, isched->min[i], isched->max[i],
147 isched->min_step, &(isched->last_exec),
148 now, nval, isched->first);
149 }
150
151 if (count == 5)
152 {
153 isched->first = 1;
154 isched->last_exec = now;
155 return 1;
156 }
157
158 return 0;
159}
160
161/* test a linked list of schedules
162 */
163int test_sched (sh_schedule_t * isched)
164{
165 sh_schedule_t * intern = isched;
166 int retval = 0;
167
168 while (intern != NULL)
169 {
170 if (test_sched_int(intern) == 1)
171 retval = 1;
172 intern = intern->next;
173 }
174 return retval;
175}
176
177static
178char DayNames[7][4] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
179static
180char MonNames[12][4] = { "jan", "feb", "mar", "apr", "may", "jun",
181 "jul", "aug", "sep", "oct", "nov", "dec" };
182
183static
184int parse_func (int i, char * p)
185{
186 int j, k, l;
187 char *tail;
188
189 errno = 0;
190 j = (int) strtol(p, &tail, 10);
191
192 if (errno != 0) /* overflow */
193 return -1;
194 if (j < 0)
195 return -1;
196 if (tail != p) /* numeric */
197 return j;
198 if (i < 3) /* names not allowed */
199 return -1;
200
201 if (i == 3)
202 {
203 for (j = 0; j < 12; ++j) {
204 l = 0;
205 /*@+charint@*//* Incompatible types for == (char, char): ??? */
206 for (k = 0; k < 3; ++k)
207 if (p[k] != '\0' && tolower(p[k]) == MonNames[j][k]) ++l;
208 /*@-charint@*/
209 if (l == 3)
210 return j;
211 }
212 }
213 if (i == 4)
214 {
215 for (j = 0; j < 7; ++j) {
216 l = 0;
217 /*@+charint@*//* Incompatible types for == (char, char): ??? */
218 for (k = 0; k < 3; ++k)
219 if (p[k] != '\0' && tolower(p[k]) == DayNames[j][k]) ++l;
220 /*@-charint@*/
221 if (l == 3)
222 return j;
223 }
224 }
225
226 return -1;
227}
228
229static
230int parse_token(int i, sh_schedule_t * isched, char * p)
231{
232 char * q;
233
234 if ( NULL != (q = strchr(p, ',')))
235 return -1;
236
237 if (*p == '*')
238 {
239 isched->min[i] = sh_schedule_min[i];
240 isched->max[i] = sh_schedule_max[i];
241 }
242 else
243 {
244 isched->min[i] = parse_func(i, p);
245 if (i == 4 && isched->min[i] == 7)
246 isched->min[i] = 0;
247 if (isched->min[i] < sh_schedule_min[i] ||
248 isched->min[i] > sh_schedule_max[i])
249 {
250 return -1;
251 }
252 if ( NULL != (q = strchr(p, '-')))
253 {
254 ++q;
255 isched->max[i] = parse_func(i, q);
256 if (i == 4 && isched->max[i] == 7)
257 isched->max[i] = 0;
258 if (isched->max[i] < sh_schedule_min[i] ||
259 isched->max[i] > sh_schedule_max[i] ||
260 isched->max[i] < isched->min[i])
261 {
262 return -1;
263 }
264 }
265 else
266 isched->max[i] = isched->min[i];
267 }
268
269 if ( NULL != (q = strchr(p, '/')))
270 {
271 ++q;
272 isched->step[i] = atoi(q);
273 if (isched->step[i] < 1 || isched->step[i] > sh_schedule_max[i])
274 {
275 return -1;
276 }
277 if (i == 4 && isched->step[i] == 7)
278 isched->step[i] = 6;
279 }
280 else
281 {
282 isched->step[i] = 1;
283 }
284
285 switch (i)
286 {
287 case 0:
288 if (isched->max[i] == isched->min[i])
289 isched->min_step = 3599;
290 else
291 isched->min_step = (isched->step[i] * 60) - 1;
292 break;
293 case 1:
294 if (isched->max[i] == isched->min[i])
295 {
296 /* fix for daylight saving time: subtract 3600 sec
297 */
298 if (isched->min_step == 3599)
299 isched->min_step = 86399 - 3600;
300 }
301 else
302 {
303 if (isched->min_step == 3599)
304 isched->min_step = (isched->step[i] * 3600) - 1;
305 }
306 break;
307 default:
308 break;
309 }
310
311 return 0;
312}
313
314static
315int parse_sched (const char * ssched, sh_schedule_t * isched)
316{
317 char * p;
318 char * copy;
319 int i = 0;
320
321 if (!ssched || !isched)
322 return -1;
323
324#ifdef TESTONLY
325 copy = malloc(strlen(ssched)+1); /* testonly code */
326#else
327 copy = SH_ALLOC(strlen(ssched)+1);
328#endif
329 strcpy(copy, ssched); /* known to fit */
330
331 p = strtok(copy, " \t"); /* parse crontab-style schedule */
332 if (!p)
333 goto err;
334 if (parse_token(i, isched, p) == -1)
335 goto err;
336
337 for (i = 1; i < 5; ++i)
338 {
339 p = strtok(NULL, " \t"); /* parse crontab-style schedule */
340 if (!p)
341 goto err;
342 if (parse_token(i, isched, p) == -1)
343 goto err;
344 }
345
346 /*
347 for (i = 0; i < 5; ++i)
348 printf("%2d MIN %3d MAX %3d STEP %3d\n",
349 i, isched->min[i], isched->max[i], isched->step[i]);
350 */
351
352 isched->last_exec = (time_t)-1;
353 isched->first = 0;
354 isched->next = NULL;
355
356#ifdef TESTONLY
357 free(copy);
358#else
359 SH_FREE(copy);
360#endif
361 return 0;
362
363 err:
364#ifdef TESTONLY
365 free(copy);
366#else
367 SH_FREE(copy);
368#endif
369 return -1;
370}
371
372int create_sched (const char * ssched, sh_schedule_t * isched)
373{
374 int j;
375
376 if (!isched || !ssched)
377 return -1;
378
379 j = parse_sched(ssched, isched);
380
381#ifdef TESTONLY
382 if (j == 0)
383 {
384 int i;
385 for (i = 0; i < 5; ++i)
386 printf("%2d MIN %3d MAX %3d STEP %3d\n",
387 i, isched->max[i], isched->min[i], isched->step[i]);
388 printf("MINSTEP %7d\n", isched->min_step);
389 printf("LASTEXEC %7ld\n", (long) isched->last_exec);
390 }
391#endif
392
393 return j;
394}
395
396/* #ifdef SCHEDULER_YES */
397#endif
398
399/**************************************************
400 *
401 * Schedule class - Test driver
402 *
403 **************************************************/
404#ifdef TESTONLY
405
406int main(int argc, char * argv[])
407{
408 sh_schedule_t isched;
409
410 if (argc < 2)
411 {
412 fprintf(stderr, "Usage: %s 'schedule'\n", argv[0]);
413 exit (1);
414 }
415
416 if (create_sched(argv[1], &isched) < 0)
417 {
418 fprintf(stderr, "Bad schedule <%s>\n", argv[1]);
419 exit (1);
420 }
421
422 while (1 == 1)
423 {
424 if (test_sched(&isched))
425 printf("EXECUTE at: %s", ctime(&(isched.last_exec)));
426 sleep (1); /* TESTONLY */
427 }
428 return 0;
429}
430#endif
Note: See TracBrowser for help on using the repository browser.