source: trunk/src/sh_schedule.c @ 1

Last change on this file since 1 was 1, checked in by katerina, 16 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.