source: trunk/src/sh_schedule.c@ 583

Last change on this file since 583 was 583, checked in by katerina, 27 hours ago

Fix for ticket #471 (autoreconf throws warnings/errors).

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