/* cron.h */
#ifndef _DBCRON_COMM_H_
#define _DBCRON_COMM_H_
#define E_NORMAL 0x01
#define E_EVERY 0x02
#define E_AREA 0x04
#define E_SLASH 0x08
#define MINUTE_EVERY 0x01
#define HOUR_EVERY 0x02
#define DAY_MON_EVERY 0x04
#define MON_YEAR_EVERY 0x08
#define DAY_WEEK_EVERY 0x10
#define FIRST_MINUTE 0
#define LAST_MINUTE 59
#define MINUTE_COUNT (LAST_MINUTE - FIRST_MINUTE + 1)
#define FIRST_HOUR 0
#define LAST_HOUR 23
#define HOUR_COUNT (LAST_HOUR - FIRST_HOUR + 1)
#define FIRST_DAYOFMON 1
#define LAST_DAYOFMON 31
#define DAYOFMON_COUNT (LAST_DAYOFMON - FIRST_DAYOFMON + 1)
#define FIRST_MONTH 1
#define LAST_MONTH 12
#define MONTH_COUNT (LAST_MONTH - FIRST_MONTH + 1)
/* note on DOW: 0 and 7 are both Sunday */
#define FIRST_DAYOFWEEK 0
#define LAST_DAYOFWEEK 7
#define DAYOFWEEK_COUNT (LAST_DAYOFWEEK - FIRST_DAYOFWEEK + 1)
#define MAX_BUF 256
#define _bit_byte(bit) \
((bit) >> 3)
#define _bit_mask(bit) \
(1 << ((bit)&0x7))
#define bitstr_size(nbits) \
((((nbits) - 1) >> 3) + 1)
#define bit_decl(name, nbits) \
(name)[bitstr_size(nbits)]
#define bit_test(name, bit) \
((name)[_bit_byte(bit)] & _bit_mask(bit))
#define bit_set(name, bit) \
(name)[_bit_byte(bit)] |= _bit_mask(bit)
#define bit_clear(name, bit) \
(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
#define bit_nclear(name, start, stop) { \
register unsigned char *_name = name; \
register int _start = start, _stop = stop; \
register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \
_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
(0xff << ((_stop&0x7) + 1))); \
} else { \
_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
while (++_startbyte < _stopbyte) \
name[_startbyte] = 0; \
_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
} \
}
#define bit_nset(name, start, stop) { \
register unsigned char *_name = name; \
register int _start = start, _stop = stop; \
register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \
_name[_startbyte] |= ((0xff << (_start&0x7)) & \
(0xff >> (7 - (_stop&0x7)))); \
} else { \
_name[_startbyte] |= 0xff << ((_start)&0x7); \
while (++_startbyte < _stopbyte) \
_name[_startbyte] = 0xff; \
_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
} \
}
typedef struct _element
{
int flag;
int low;
int high;
int step;
}ELEMENT;
typedef struct _date_rec
{
ELEMENT minute;
ELEMENT hour;
ELEMENT day_of_mon;
ELEMENT mon_of_year;
ELEMENT day_of_week;
}DATE_REC;
typedef struct _entry
{
int flags;
unsigned char bit_decl(minute, MINUTE_COUNT);
unsigned char bit_decl(hour, HOUR_COUNT);
unsigned char bit_decl(day_of_mon, DAYOFMON_COUNT);
unsigned char bit_decl(mon_of_year, MONTH_COUNT);
unsigned char bit_decl(day_of_week, DAYOFWEEK_COUNT);
char command[MAX_BUF];
struct _entry *next;
}ENTRY;
#endif //_DBCRON_COMM_H_
/* cron.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/time.h>
#include <time.h>
//#include <sqlite3.h>
#include "dbcron_comm.h"
static ENTRY *head = NULL;
static ENTRY *tail = NULL;
int set_bit(unsigned char *bits, int low, int high, int number)
{
if (number < low || number > high)
return -1;
bit_set(bits, (number - low));
return 0;
}
int set_element(unsigned char *bits, ELEMENT element, int low, int high)
{
int i;
int num1;
int num2;
int num3;
bit_nclear(bits, 0, (high - low + 1));
if (E_EVERY == element.flag)
{
num1 = low;
num2 = high;
}
else if (E_NORMAL == element.flag)
{
num1 = element.low;
set_bit(bits, low, high, num1);
return 0;
}
else if (E_AREA == element.flag)
{
num1 = element.low;
num2 = element.high;
}
num3 = element.step;
if (num3 <= 0)
return -1;
for (i = num1; i <= num2; i += num3)
{
set_bit(bits, low, high, i);
}
return 0;
}
int load_entry(ENTRY *pEntry, DATE_REC *pDate)
{
if (E_EVERY == pDate->minute.flag)
pEntry->flags |= MINUTE_EVERY;
set_element(pEntry->minute, pDate->minute, FIRST_MINUTE, LAST_MINUTE);
if (E_EVERY == pDate->hour.flag)
pEntry->flags |= HOUR_EVERY;
set_element(pEntry->hour, pDate->hour, FIRST_HOUR, LAST_HOUR);
if (E_EVERY == pDate->day_of_mon.flag)
pEntry->flags |= DAY_MON_EVERY;
set_element(pEntry->day_of_mon, pDate->day_of_mon, FIRST_DAYOFMON, LAST_DAYOFMON);
if (E_EVERY == pDate->mon_of_year.flag)
pEntry->flags |= MON_YEAR_EVERY;
set_element(pEntry->mon_of_year, pDate->mon_of_year, FIRST_MONTH, LAST_MONTH);
if (E_EVERY == pDate->day_of_week.flag)
pEntry->flags |= DAY_WEEK_EVERY;
set_element(pEntry->day_of_week, pDate->day_of_week, FIRST_DAYOFWEEK, LAST_DAYOFWEEK);
if (bit_test(pEntry->day_of_week, 0) || bit_test(pEntry->day_of_week, 7))
{
bit_set(pEntry->day_of_week, 0);
bit_set(pEntry->day_of_week, 7);
}
return 0;
}
ENTRY *add_entry(void)
{
ENTRY *pEntry;
pEntry = (ENTRY *)malloc(sizeof(ENTRY));
if (NULL == pEntry)
{
return NULL;
}
memset(pEntry, 0, sizeof(ENTRY));
pEntry->next = NULL;
if (NULL == head)
head = pEntry;
else
tail->next = pEntry;
tail = pEntry;
return pEntry;
}
void del_entry()
{
ENTRY *pEntry;
if (NULL == head)
return;
pEntry = head;
while (head)
{
pEntry = head->next;
free(head);
head = pEntry;
}
head = NULL;
tail = NULL;
}
void display_entry()
{
#if 1
ENTRY *pe;
int i;
bool n;
pe = head;
while (pe)
{
printf("minute: ");
for (i = 0; i <= LAST_MINUTE; i ++)
{
n = bit_test(pe->minute, i);
printf("%d:%d ", i, n);
}
printf("\n");
printf("hour: ");
for (i = 0; i <= LAST_HOUR; i ++)
{
n = bit_test(pe->hour, i);
printf("%d:%d ", i, n);
}
printf("\n");
printf("day of mon: ");
for (i = 0; i < LAST_DAYOFMON; i ++)
{
n = bit_test(pe->day_of_mon, i);
printf("%d:%d ", i, n);
}
printf("\n");
printf("mon of year: ");
for (i = 0; i < LAST_MONTH; i ++)
{
n = bit_test(pe->mon_of_year, i);
printf("%d:%d ", i, n);
}
printf("\n");
printf("day of week: ");
for (i = 0; i <= LAST_DAYOFWEEK; i ++)
{
n = bit_test(pe->day_of_week, i);
printf("%d:%d ", i, n);
}
printf("\n");
printf("\n");
pe = pe->next;
}
#endif
}
void do_job(time_t current_time)
{
struct tm *p_tm;
ENTRY *pe;
int minute;
int hour;
int day_of_month;
int month_of_year;
int day_of_week;
p_tm = localtime(¤t_time);
pe = head;
minute = p_tm->tm_min - FIRST_MINUTE;
hour = p_tm->tm_hour - FIRST_HOUR;
day_of_month = p_tm->tm_mday - FIRST_DAYOFMON;
month_of_year = p_tm->tm_mon + 1 - FIRST_MONTH;
day_of_week = p_tm->tm_wday - FIRST_DAYOFWEEK;
#if 1
printf("%d, %d, %d, %d, %d\n",
minute,
hour,
day_of_month,
month_of_year,
day_of_week);
#endif
while (pe)
{
if (bit_test(pe->minute, minute) &&
bit_test(pe->hour, hour) &&
bit_test(pe->day_of_mon, day_of_month) &&
bit_test(pe->mon_of_year, month_of_year) &&
bit_test(pe->day_of_week, day_of_week))
{
printf("%s\n", pe->command);
}
pe = pe->next;
}
}
void cron_sleep(int target)
{
int seconds_to_wait;
seconds_to_wait = (int)(target - time((time_t *)NULL)) + 1;
if (seconds_to_wait > 0 && seconds_to_wait < 65)
sleep((unsigned int) seconds_to_wait);
}
int main(int argc, char *argv[])
{
/* 测试例程 */
ENTRY *pEntry;
DATE_REC date;
int running_time;
date.minute.flag = E_EVERY;
date.minute.low = FIRST_MINUTE;
date.minute.high = LAST_MINUTE;
date.minute.step = 2;
date.hour.flag = E_NORMAL;
date.hour.low = 9;
date.hour.high = LAST_HOUR;
date.hour.step = 1;
date.day_of_mon.flag = E_EVERY;
date.day_of_mon.low = FIRST_DAYOFMON;
date.day_of_mon.high = LAST_DAYOFMON;
date.day_of_mon.step = 1;
date.mon_of_year.flag = E_EVERY;
date.mon_of_year.low = FIRST_MONTH;
date.mon_of_year.high = LAST_MONTH;
date.mon_of_year.step = 1;
date.day_of_week.flag = E_EVERY;
date.day_of_week.low = FIRST_DAYOFWEEK;
date.day_of_week.high = LAST_DAYOFWEEK;
date.day_of_week.step = 1;
pEntry = add_entry();
load_entry(pEntry, &date);
strcpy(pEntry->command, "Hello");
date.minute.flag = E_EVERY;
date.minute.low = FIRST_MINUTE;
date.minute.high = LAST_MINUTE;
date.minute.step = 3;
date.hour.flag = E_NORMAL;
date.hour.low = 9;
date.hour.high = LAST_HOUR;
date.hour.step = 1;
date.day_of_mon.flag = E_EVERY;
date.day_of_mon.low = FIRST_DAYOFMON;
date.day_of_mon.high = LAST_DAYOFMON;
date.day_of_mon.step = 1;
date.mon_of_year.flag = E_EVERY;
date.mon_of_year.low = FIRST_MONTH;
date.mon_of_year.high = LAST_MONTH;
date.mon_of_year.step = 1;
date.day_of_week.flag = E_EVERY;
date.day_of_week.low = FIRST_DAYOFWEEK;
date.day_of_week.high = LAST_DAYOFWEEK;
date.day_of_week.step = 1;
pEntry = add_entry();
load_entry(pEntry, &date);
strcpy(pEntry->command, "Welcome");
display_entry();
running_time = time(NULL);
while (1)
{
do_job(running_time);
running_time += 60;
cron_sleep(running_time);
}
return 0;
}