You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
622 lines
14 KiB
C
622 lines
14 KiB
C
/*
|
|
* binkleyforce -- unix FTN mailer project
|
|
*
|
|
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "confread.h"
|
|
#include "logger.h"
|
|
#include "util.h"
|
|
|
|
static const char *months[] =
|
|
{
|
|
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
|
};
|
|
|
|
int time_settimer(time_t *timer, int value)
|
|
{
|
|
*timer = time(NULL) + value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int time_timerout(time_t timer)
|
|
{
|
|
if( timer > 0 && time(NULL) >= timer )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int time_timeleft(time_t timer)
|
|
{
|
|
if( timer > 0 )
|
|
return MAX(time(NULL) - timer, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int time_elapsed(time_t since_time)
|
|
{
|
|
if( since_time > 0 )
|
|
{
|
|
int yield = time(NULL) - since_time;
|
|
return ( yield > 0 ) ? yield : 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Put time string into buffer, according to the format
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer
|
|
* buflen buffer size
|
|
* fmt format string (`man strftime' for more information)
|
|
* t seconds since 1970.. you know..
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_format(char *buffer, size_t buflen, const char *fmt, time_t t)
|
|
{
|
|
struct tm *tm;
|
|
|
|
if( !t ) t = time(&t);
|
|
|
|
tm = localtime(&t);
|
|
|
|
if( strftime(buffer, buflen, fmt, tm) == 0 )
|
|
{
|
|
strnxcpy(buffer, "invalid format", buflen);
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Put time string into buffer (time format depends on the locale settings).
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer
|
|
* buflen buffer size
|
|
* t seconds since 1970.. you know..
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_long(char *buffer, size_t buflen, time_t t)
|
|
{
|
|
char *sptr;
|
|
|
|
if( !t ) time(&t);
|
|
|
|
sptr = ctime(&t);
|
|
strnxcpy(buffer, sptr, buflen);
|
|
|
|
return string_chomp(buffer);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Put time string into buffer (e.g. My birth day is "Aug 11 07:20:00").
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer
|
|
* buflen buffer size
|
|
* t seconds since 1970.. you know..
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_log(char *buffer, size_t buflen, time_t t)
|
|
{
|
|
struct tm *ptm;
|
|
|
|
ASSERT(buflen > 16);
|
|
|
|
if( !t ) time(&t);
|
|
|
|
ptm = localtime(&t);
|
|
sprintf(buffer, "%3s %02d %02d:%02d:%02d",
|
|
months[ptm->tm_mon], ptm->tm_mday,
|
|
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Put date+time string into buffer. Special format for netmail message
|
|
* headers.
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer
|
|
* buflen buffer size
|
|
* t seconds since 1970.. you know..
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_msghdr(char *buffer, time_t t)
|
|
{
|
|
struct tm *ptm;
|
|
|
|
if( !t ) time(&t);
|
|
|
|
ptm = localtime(&t);
|
|
sprintf(buffer, "%02d %3s %02d %02d:%02d:%02d",
|
|
ptm->tm_mday, months[ptm->tm_mon],
|
|
(ptm->tm_year < 100) ? ptm->tm_year : ptm->tm_year % 100,
|
|
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get TimeZone for our location
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Return value:
|
|
* Offset in minutes
|
|
*/
|
|
long time_gmtoffset(void)
|
|
{
|
|
time_t tt = time(NULL);
|
|
struct tm local = *localtime(&tt);
|
|
struct tm gmt = *gmtime(&tt);
|
|
long tz = gmt.tm_yday - local.tm_yday;
|
|
|
|
if( tz > 1 )
|
|
tz = -24;
|
|
else if( tz < -1 )
|
|
tz = 24;
|
|
else
|
|
tz *= 24;
|
|
|
|
tz += gmt.tm_hour - local.tm_hour;
|
|
tz *= 60;
|
|
tz += gmt.tm_min - local.tm_min;
|
|
|
|
return tz;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get TimeZone for our location as pointer to the null terminated string
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer (must be at least 6 bytes)
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string (e.g. "+0400")
|
|
*/
|
|
char *time_string_gmtoffset(char *buffer)
|
|
{
|
|
long tz = time_gmtoffset();
|
|
char sign = (tz > 0)?'+':'-';
|
|
int hour = tz/60;
|
|
int mint = tz%60;
|
|
|
|
sprintf(buffer, "%c%02d%02d", sign, hour, mint);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get time in native format from seconds counter (e.g. "1:30:10")
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer (must be at least 9 bytes)
|
|
* timer number of seconds
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_timer(char *buffer, int timer)
|
|
{
|
|
int hour, min, sec;
|
|
|
|
hour = (timer/3600);
|
|
min = (timer%3600)/60;
|
|
sec = (timer%60);
|
|
|
|
if( hour )
|
|
sprintf(buffer, "%02d:%02d:%02d", (hour < 100) ? hour : 99, min, sec);
|
|
else
|
|
sprintf(buffer, "%02d:%02d", min, sec);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get approximate interval in native format (e.g. "1 day", "3 hours")
|
|
*
|
|
* Arguments:
|
|
* buffer pointer to the destination buffer (must be large enough)
|
|
* seconds time interval in seconds
|
|
*
|
|
* Return value:
|
|
* Pointer to the resulting string
|
|
*/
|
|
char *time_string_approx_interval(char *buffer, int seconds)
|
|
{
|
|
if( seconds < 0 )
|
|
strcpy(buffer, "error");
|
|
else if( seconds == 0 )
|
|
strcpy(buffer, "up-to-date");
|
|
else if( seconds == 1 )
|
|
strcpy(buffer, "1 second");
|
|
else if( seconds < 60 )
|
|
sprintf(buffer, "%d seconds", seconds);
|
|
else if( seconds < 120 )
|
|
strcpy(buffer, "1 minute");
|
|
else if( seconds < 3600 )
|
|
sprintf(buffer, "%d minutes", seconds/60);
|
|
else if( seconds < 7200 )
|
|
strcpy(buffer, "1 hour");
|
|
else if( seconds < 86400 )
|
|
sprintf(buffer, "%d hours", seconds/3600);
|
|
else if( seconds < 172800 )
|
|
strcpy(buffer, "1 day");
|
|
else if( seconds < 999*86400 )
|
|
sprintf(buffer, "%d days", seconds/86400);
|
|
else
|
|
sprintf(buffer, "%d years", seconds/(366*86400));
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Check time for conforming to the time interval specified by string
|
|
*
|
|
* Arguments:
|
|
* str pointer to the time interval string
|
|
* now time to check (most often it is current time)
|
|
*
|
|
* Return value:
|
|
* Zero value if time conforms, 1 if not, and -1 if specified time interval
|
|
* string is incorrect
|
|
*/
|
|
int time_check(const char *str, struct tm *now)
|
|
{
|
|
int h1, h2, m1, m2, beg, end, cur, day;
|
|
bool dayok = FALSE;
|
|
bool timeok = FALSE;
|
|
|
|
ASSERT(str != NULL && now != NULL);
|
|
|
|
if( *str == '\0' ) return 1;
|
|
|
|
if( strncasecmp(str, "Sun", 3) == 0 ) day = 0;
|
|
else if( strncasecmp(str, "Mon", 3) == 0 ) day = 1;
|
|
else if( strncasecmp(str, "Tue", 3) == 0 ) day = 2;
|
|
else if( strncasecmp(str, "Wed", 3) == 0 ) day = 3;
|
|
else if( strncasecmp(str, "Thu", 3) == 0 ) day = 4;
|
|
else if( strncasecmp(str, "Fri", 3) == 0 ) day = 5;
|
|
else if( strncasecmp(str, "Sat", 3) == 0 ) day = 6;
|
|
else if( strncasecmp(str, "Any", 3) == 0 ) day = -1;
|
|
else if( strncasecmp(str, "Wk", 2) == 0 ) day = -2;
|
|
else if( strncasecmp(str, "We", 2) == 0 ) day = -3;
|
|
else day = -4;
|
|
|
|
if( day >= 0 )
|
|
{
|
|
dayok = (now->tm_wday == day);
|
|
str += 3;
|
|
}
|
|
else
|
|
{
|
|
switch(day) {
|
|
case -3:
|
|
dayok = ( (now->tm_wday == 0) || (now->tm_wday == 6) );
|
|
str += 2;
|
|
break;
|
|
case -2:
|
|
dayok = ( (now->tm_wday != 0) && (now->tm_wday != 6) );
|
|
str += 2;
|
|
break;
|
|
case -1:
|
|
str += 3;
|
|
default:
|
|
dayok = TRUE;
|
|
}
|
|
}
|
|
|
|
if( !dayok ) return 1;
|
|
|
|
if( *str == '\0' )
|
|
return (day == -4) ? -1 : 0;
|
|
|
|
if( sscanf(str, "%02d:%02d-%02d:%02d", &h1, &m1, &h2, &m2) != 4 )
|
|
return -1;
|
|
|
|
cur = now->tm_hour*60 + now->tm_min;
|
|
beg = h1*60 + m1;
|
|
end = h2*60 + m2;
|
|
|
|
if( end > beg )
|
|
timeok = ( (cur >= beg) && (cur <= end) );
|
|
else
|
|
timeok = ( (cur >= beg) || (cur <= end) );
|
|
|
|
DEB((D_INFO, "checktime: is %02d:%02d between %02d:%02d and %02d:%02d? %s!",
|
|
now->tm_hour,now->tm_min, h1, m1, h2, m2, timeok ? "Yes" : "No"));
|
|
|
|
return !timeok;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Check time for conforming to the time intervals
|
|
*
|
|
* Arguments:
|
|
* timestr pointer to the time intervals string
|
|
* tim time to check (most often it is current time)
|
|
*
|
|
* Return value:
|
|
* Zero value if time conforms, 1 if not, and -1 if specified time interval
|
|
* string is incorrect
|
|
*/
|
|
int time_checkintervals(const char *timestr, struct tm *now)
|
|
{
|
|
char *str, *p;
|
|
|
|
ASSERT(timestr != NULL);
|
|
|
|
str = xstrcpy(timestr);
|
|
|
|
for( p = strtok(str, ","); p; p = strtok(NULL, ",") )
|
|
{
|
|
if( *p )
|
|
{
|
|
switch(time_check(p, now)) {
|
|
case 0:
|
|
return 0;
|
|
case -1:
|
|
return -1;
|
|
case 1:
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int timevec_add(s_timevec *dest, int day_beg, int day_end, long beg, long end)
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* Check for dupes. TODO: more complex checks
|
|
*/
|
|
for( i = 0; i < dest->num; i++ )
|
|
{
|
|
if( dest->tvec[i].day_beg <= day_beg
|
|
&& dest->tvec[i].day_end >= day_end
|
|
&& dest->tvec[i].beg == beg
|
|
&& dest->tvec[i].end == end )
|
|
return 0;
|
|
}
|
|
|
|
if( dest->num >= TIMEVEC_MAX_ELEMENTS )
|
|
return -1;
|
|
|
|
dest->tvec[dest->num].day_beg = day_beg;
|
|
dest->tvec[dest->num].day_end = day_end;
|
|
dest->tvec[dest->num].beg = beg;
|
|
dest->tvec[dest->num].end = end;
|
|
dest->num++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Parse one time interval. Only uucico like time format is supported yet.
|
|
*
|
|
* Arguments:
|
|
* dest pointer to the destination time storage structure
|
|
* str time string to parse
|
|
*
|
|
* Return value:
|
|
* Zero value on success, and -1 for incorrect time strings
|
|
*/
|
|
int timevec_parse(s_timevec *dest, const char *str)
|
|
{
|
|
int beg_hour = 0;
|
|
int end_hour = 0;
|
|
int beg_min = 0;
|
|
int end_min = 0;
|
|
enum day beg_day;
|
|
enum day end_day;
|
|
int beg = 0;
|
|
int end = 0;
|
|
|
|
if( strncasecmp(str, "Sun", 3) == 0 )
|
|
beg_day = DAY_SUNDAY;
|
|
else if( strncasecmp(str, "Mon", 3) == 0 )
|
|
beg_day = DAY_MONDAY;
|
|
else if( strncasecmp(str, "Tue", 3) == 0 )
|
|
beg_day = DAY_TUESDAY;
|
|
else if( strncasecmp(str, "Wed", 3) == 0 )
|
|
beg_day = DAY_WEDNESDAY;
|
|
else if( strncasecmp(str, "Thu", 3) == 0 )
|
|
beg_day = DAY_THURSDAY;
|
|
else if( strncasecmp(str, "Fri", 3) == 0 )
|
|
beg_day = DAY_FRIDAY;
|
|
else if( strncasecmp(str, "Sat", 3) == 0 )
|
|
beg_day = DAY_SATURDAY;
|
|
else if( strncasecmp(str, "Any", 3) == 0 )
|
|
beg_day = DAY_ANY;
|
|
else if( strncasecmp(str, "Wk", 2) == 0 )
|
|
beg_day = DAY_WORKDAY;
|
|
else if( strncasecmp(str, "We", 2) == 0 )
|
|
beg_day = DAY_WEEKEND;
|
|
else
|
|
beg_day = DAY_UNDEF;
|
|
|
|
end_day = beg_day;
|
|
|
|
if( beg_day >= DAY_MONDAY && beg_day <= DAY_SUNDAY )
|
|
str += 3;
|
|
else if( beg_day == DAY_ANY )
|
|
str += 3;
|
|
else if( beg_day == DAY_WORKDAY || beg_day == DAY_WEEKEND )
|
|
str += 2;
|
|
|
|
if( sscanf(str, "%02d:%02d-%02d:%02d", &beg_hour, &beg_min, &end_hour, &end_min) != 4 )
|
|
return -1;
|
|
|
|
beg = beg_hour * 60 + beg_min;
|
|
end = end_hour * 60 + end_min;
|
|
|
|
if( beg == end )
|
|
return -1;
|
|
|
|
switch(beg_day) {
|
|
case DAY_MONDAY:
|
|
case DAY_TUESDAY:
|
|
case DAY_WEDNESDAY:
|
|
case DAY_THURSDAY:
|
|
case DAY_FRIDAY:
|
|
case DAY_SATURDAY:
|
|
case DAY_SUNDAY:
|
|
timevec_add(dest, beg_day, end_day, beg, end);
|
|
break;
|
|
case DAY_WORKDAY:
|
|
timevec_add(dest, DAY_MONDAY, DAY_FRIDAY, beg, end);
|
|
break;
|
|
case DAY_WEEKEND:
|
|
timevec_add(dest, DAY_SATURDAY, DAY_SUNDAY, beg, end);
|
|
break;
|
|
default:
|
|
timevec_add(dest, DAY_MONDAY, DAY_SUNDAY, beg, end);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int timevec_parse_list(s_timevec *dest, const char *str)
|
|
{
|
|
char *p = NULL;
|
|
char *tmp = xstrcpy(str);
|
|
int rc = 0;
|
|
|
|
for( p = strtok(tmp, ","); p; p = strtok(NULL, ",") )
|
|
{
|
|
if( *p && timevec_parse(dest, p) == -1 )
|
|
rc = -1;
|
|
}
|
|
|
|
free(tmp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int timevec_check(const s_timevec *tv, const struct tm *now)
|
|
{
|
|
int i;
|
|
bool ok = FALSE;
|
|
int cur = now->tm_hour * 60 + now->tm_min;
|
|
int cur_day = DAY_UNDEF;
|
|
|
|
if( now->tm_wday == 0 )
|
|
cur_day = DAY_SUNDAY;
|
|
else if( now->tm_wday == 1 )
|
|
cur_day = DAY_MONDAY;
|
|
else if( now->tm_wday == 2 )
|
|
cur_day = DAY_TUESDAY;
|
|
else if( now->tm_wday == 3 )
|
|
cur_day = DAY_WEDNESDAY;
|
|
else if( now->tm_wday == 4 )
|
|
cur_day = DAY_THURSDAY;
|
|
else if( now->tm_wday == 5 )
|
|
cur_day = DAY_FRIDAY;
|
|
else if( now->tm_wday == 6 )
|
|
cur_day = DAY_SATURDAY;
|
|
else
|
|
{
|
|
log("timevec_check: error 'tm->tm_wday' is out of range");
|
|
return -1;
|
|
}
|
|
|
|
for( i = 0; i < tv->num; i++ )
|
|
{
|
|
if( (cur_day >= tv->tvec[i].day_beg)
|
|
&& (cur_day <= tv->tvec[i].day_end) )
|
|
{
|
|
int beg = tv->tvec[i].beg;
|
|
int end = tv->tvec[i].end;
|
|
|
|
if( end > beg )
|
|
ok = ( (cur >= beg) && (cur <= end) );
|
|
else
|
|
ok = ( (cur >= beg) || (cur <= end) );
|
|
|
|
if( ok ) break;
|
|
}
|
|
}
|
|
|
|
return ok ? 0 : 1;
|
|
}
|
|
|
|
char *timevec_string(char *buffer, const s_timevec *tv, size_t buflen)
|
|
{
|
|
int i;
|
|
char *ptr = buffer;
|
|
|
|
*ptr = '\0';
|
|
|
|
for( i = 0; i < tv->num; i++ )
|
|
{
|
|
if( tv->tvec[i].day_beg == DAY_MONDAY
|
|
&& tv->tvec[i].day_end == DAY_SUNDAY )
|
|
{
|
|
sprintf(ptr, "%02ld:%02ld-%02ld:%02ld,",
|
|
tv->tvec[i].beg / 60, tv->tvec[i].beg % 60,
|
|
tv->tvec[i].end / 60, tv->tvec[i].end % 60);
|
|
}
|
|
else if( tv->tvec[i].day_beg == tv->tvec[i].day_end )
|
|
{
|
|
sprintf(ptr, "%d.%02ld:%02ld-%02ld:%02ld,", tv->tvec[i].day_beg,
|
|
tv->tvec[i].beg / 60, tv->tvec[i].beg % 60,
|
|
tv->tvec[i].end / 60, tv->tvec[i].end % 60);
|
|
}
|
|
else
|
|
{
|
|
sprintf(ptr, "%d.%02ld:%02ld-%d.%02ld:%02ld,",
|
|
tv->tvec[i].day_beg, tv->tvec[i].beg / 60, tv->tvec[i].beg % 60,
|
|
tv->tvec[i].day_end, tv->tvec[i].end / 60, tv->tvec[i].end % 60);
|
|
}
|
|
|
|
ptr += strlen(ptr);
|
|
}
|
|
|
|
if( ptr > buffer )
|
|
*(ptr - 1) = '\0';
|
|
|
|
return buffer;
|
|
}
|
|
|
|
bool timevec_isdefined(const s_timevec *tv)
|
|
{
|
|
return tv->num ? TRUE : FALSE;
|
|
}
|
|
|
|
bool timevec_isnow(const s_timevec *tv, const struct tm *now)
|
|
{
|
|
return ( timevec_check(tv, now) == 0 ) ? TRUE : FALSE;
|
|
}
|
|
|
|
/* end of u_time.c */
|