Wed Jan 27 20:02:41 2016

Asterisk developer's documentation


localtime.c File Reference

#include "asterisk.h"
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

struct  locale_entry
struct  localelist
struct  lsinfo
 leap second information More...
struct  rule
struct  state
struct  ttinfo
 time type information More...
struct  zonelist

Defines

#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
#define DAY_OF_YEAR   1
#define JULIAN_DAY   0
#define MONTH_NTH_DAY_OF_WEEK   2
#define MY_TZNAME_MAX   255
#define OPEN_MODE   O_RDONLY
#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
#define TZ_ABBR_ERR_CHAR   '_'
#define TZ_ABBR_MAX_LEN   16
#define TZ_STRLEN_MAX   255
#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"

Functions

static void add_notify (struct state *sp, const char *path)
void ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone)
struct ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
 Timezone-independent version of localtime_r(3).
void ast_localtime_wakeup_monitor (struct ast_test *info)
struct timeval ast_mktime (struct ast_tm *tmp, const char *zone)
 Timezone-independent version of mktime(3).
const char * ast_setlocale (const char *locale)
 Set the thread-local representation of the current locale.
int ast_strftime (char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
 Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds.
int ast_strftime_locale (char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
char * ast_strptime (const char *s, const char *format, struct ast_tm *tm)
 Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.
char * ast_strptime_locale (const char *s, const char *format, struct ast_tm *tm, const char *locale)
static struct stateast_tzset (const char *zone)
void clean_time_zones (void)
static long detzcode (const char *const codep)
static time_t detzcode64 (const char *const codep)
static int differ_by_repeat (const time_t t1, const time_t t0)
static struct locale_entryfind_by_locale (locale_t locale)
static struct locale_entryfind_by_name (const char *name)
static const char * getnum (const char *strp, int *nump, const int min, const int max)
 Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.
static const char * getoffset (const char *strp, long *offsetp)
 Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
static const char * getqzname (const char *strp, const int delim)
 Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.
static const char * getrule (const char *strp, struct rule *rulep)
 Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.
static const char * getsecs (const char *strp, long *const secsp)
 Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.
static const char * getzname (const char *strp)
 Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.
static int gmtload (struct state *sp)
static struct ast_tmgmtsub (const struct timeval *timep, const long offset, struct ast_tm *tmp)
static int increment_overflow (int *number, int delta)
 Simplified normalize logic courtesy Paul Eggert.
static void * inotify_daemon (void *data)
static int leaps_thru_end_of (const int y)
 Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.
static struct ast_tmlocalsub (const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
static int long_increment_overflow (long *number, int delta)
static int long_normalize_overflow (long *tensptr, int *unitsptr, const int base)
static int normalize_overflow (int *tensptr, int *unitsptr, const int base)
static int tzparse P ((const char *name, struct state *sp, int lastditch))
static int tzload P ((const char *name, struct state *sp, int doextend))
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
static int tmcomp P ((const struct ast_tm *atmp, const struct ast_tm *btmp))
static struct ast_tm *timesub P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp))
static struct timeval time2sub P ((struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp))
static struct timeval time2 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp))
static struct timeval time1 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp))
static int normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
static int long_normalize_overflow P ((long *tensptr, int *unitsptr, const int base))
static int long_increment_overflow P ((long *number, int delta))
static int leaps_thru_end_of P ((int y))
static int increment_overflow P ((int *number, int delta))
static struct ast_tm *localsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp))
static struct ast_tm *gmtsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp))
static int gmtload P ((struct state *sp))
static const char *getrule P ((const char *strp, struct rule *rulep))
static const char *getoffset P ((const char *strp, long *offsetp))
static const char *getsecs P ((const char *strp, long *secsp))
static const char *getnum P ((const char *strp, int *nump, int min, int max))
static const char *getqzname P ((const char *strp, const int delim))
static const char *getzname P ((const char *strp))
static int differ_by_repeat P ((time_t t1, time_t t0))
static long detzcode P ((const char *codep))
static const char * store_by_locale (locale_t prevlocale)
static struct timeval time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
static struct timeval time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
static struct timeval time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
static struct ast_tmtimesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
static int tmcomp (const struct ast_tm *atmp, const struct ast_tm *btmp)
static time_t transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset)
 Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
static int tzload (const char *name, struct state *const sp, const int doextend)
static int tzparse (const char *name, struct state *sp, const int lastditch)

Variables

static char elsieid [] = "@(#)localtime.c 8.5"
static const char gmt [] = "GMT"
static ast_cond_t initialization
static ast_mutex_t initialization_lock
static int inotify_fd = -1
static pthread_t inotify_thread = AST_PTHREADT_NULL
static const int mon_lengths [2][MONSPERYEAR]
static struct timeval WRONG = { 0, 0 }
static const int year_lengths [2]

Detailed Description

Multi-timezone Localtime code

The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/

Definition in file localtime.c.


Define Documentation

#define BIGGEST ( a,
 )     (((a) > (b)) ? (a) : (b))

Definition at line 148 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 205 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 204 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 206 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 154 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 109 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 93 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 98 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 89 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 157 of file localtime.c.

#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"
Note:
The DST rules to use if TZ has no rules and we can't load TZDEFRULES. We default to US rules as of 1999-08-17. POSIX 1003.1 section 8.1.1 says that the default DST rules are implementation dependent; for historical reasons, US rules are a common default.

Definition at line 130 of file localtime.c.

Referenced by tzparse().


Function Documentation

static void add_notify ( struct state sp,
const char *  path 
) [static]

Definition at line 328 of file localtime.c.

References ast_cond_init, ast_cond_wait, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, FILENAME_MAX, inotify_daemon(), and state::wd.

Referenced by tzload().

00329 {
00330    if (inotify_thread == AST_PTHREADT_NULL) {
00331       ast_cond_init(&initialization, NULL);
00332       ast_mutex_init(&initialization_lock);
00333       ast_mutex_lock(&initialization_lock);
00334       if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) {
00335          /* Give the thread a chance to initialize */
00336          ast_cond_wait(&initialization, &initialization_lock);
00337       } else {
00338          fprintf(stderr, "Unable to start notification thread\n");
00339          ast_mutex_unlock(&initialization_lock);
00340          return;
00341       }
00342       ast_mutex_unlock(&initialization_lock);
00343    }
00344 
00345    if (inotify_fd > -1) {
00346       char fullpath[FILENAME_MAX + 1] = "";
00347       if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
00348          /* If file the symlink points to changes */
00349          sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
00350       } else {
00351          sp->wd[1] = -1;
00352       }
00353       /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
00354       sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
00355 #ifdef IN_DONT_FOLLOW   /* Only defined in glibc 2.5 and above */
00356          | IN_DONT_FOLLOW
00357 #endif
00358       );
00359    }
00360 }

void ast_get_dst_info ( const time_t *const   timep,
int *  dst_enabled,
time_t *  dst_start,
time_t *  dst_end,
int *  gmt_off,
const char *const   zone 
)

Definition at line 1585 of file localtime.c.

References ast_tzset(), state::ats, AVGSECSPERYEAR, state::goahead, state::goback, int_fast64_t, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by set_timezone_variables().

01586 {
01587    int i;   
01588    int transition1 = -1;
01589    int transition2 = -1;
01590    time_t      seconds;
01591    int  bounds_exceeded = 0;
01592    time_t  t = *timep;
01593    const struct state *sp;
01594    
01595    if (NULL == dst_enabled)
01596       return;
01597    *dst_enabled = 0;
01598 
01599    if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
01600       return;
01601 
01602    *gmt_off = 0; 
01603    
01604    sp = ast_tzset(zone);
01605    if (NULL == sp) 
01606       return;
01607    
01608    /* If the desired time exceeds the bounds of the defined time transitions  
01609    * then give give up on determining DST info and simply look for gmt offset 
01610    * This requires that I adjust the given time using increments of Gregorian 
01611    * repeats to place the time within the defined time transitions in the 
01612    * timezone structure.  
01613    */
01614    if ((sp->goback && t < sp->ats[0]) ||
01615          (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01616       time_t      tcycles;
01617       int_fast64_t   icycles;
01618 
01619       if (t < sp->ats[0])
01620          seconds = sp->ats[0] - t;
01621       else  seconds = t - sp->ats[sp->timecnt - 1];
01622       --seconds;
01623       tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01624       ++tcycles;
01625       icycles = tcycles;
01626       if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01627          return;
01628       seconds = icycles;
01629       seconds *= YEARSPERREPEAT;
01630       seconds *= AVGSECSPERYEAR;
01631       if (t < sp->ats[0])
01632          t += seconds;
01633       else
01634          t -= seconds;
01635       
01636       if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
01637          return;  /* "cannot happen" */
01638 
01639       bounds_exceeded = 1;
01640    }
01641 
01642    if (sp->timecnt == 0 || t < sp->ats[0]) {
01643       /* I have no transition times or I'm before time */
01644       *dst_enabled = 0;
01645       /* Find where I can get gmtoff */
01646       i = 0;
01647       while (sp->ttis[i].tt_isdst)
01648          if (++i >= sp->typecnt) {
01649          i = 0;
01650          break;
01651          }
01652          *gmt_off = sp->ttis[i].tt_gmtoff;
01653          return;
01654    } 
01655 
01656    for (i = 1; i < sp->timecnt; ++i) {
01657       if (t < sp->ats[i]) {
01658          transition1 = sp->types[i - 1];
01659          transition2 = sp->types[i];
01660          break;
01661       } 
01662    }
01663    /* if I found transition times that do not bounded the given time and these correspond to 
01664       or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
01665    if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
01666          (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
01667       *dst_enabled = 0;
01668       *gmt_off     = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
01669    } else {
01670       /* I have valid daylight savings information. */
01671       if(sp->ttis[transition2].tt_isdst) 
01672          *gmt_off = sp->ttis[transition1].tt_gmtoff;
01673       else 
01674          *gmt_off = sp->ttis[transition2].tt_gmtoff;
01675 
01676       /* If I adjusted the time earlier, indicate that the dst is invalid */
01677       if (!bounds_exceeded) {
01678          *dst_enabled = 1;
01679          /* Determine which of the bounds is the start of daylight savings and which is the end */
01680          if(sp->ttis[transition2].tt_isdst) {
01681             *dst_start = sp->ats[i];
01682             *dst_end = sp->ats[i -1];
01683          } else {
01684             *dst_start = sp->ats[i -1];
01685             *dst_end = sp->ats[i];
01686          }
01687       }
01688    }  
01689    return;
01690 }

struct ast_tm* ast_localtime ( const struct timeval *  timep,
struct ast_tm p_tm,
const char *  zone 
) [read]

Timezone-independent version of localtime_r(3).

Parameters:
timep Current time, including microseconds
p_tm Pointer to memory where the broken-out time will be stored
zone Text string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
p_tm is returned for convenience

Definition at line 1570 of file localtime.c.

References ast_tzset(), and localsub().

Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_log(), ast_queue_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_th(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_th(), ast_say_date_with_format_vi(), ast_say_date_with_format_zh(), ast_say_datetime_de(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_from_now_pt(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_hu(), ast_say_datetime_ka(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_th(), ast_say_time_zh(), build_device(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), conf_run(), enc_ie_date(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), manager_log(), mstime(), odbc_log(), packdate(), pgsql_log(), phone_call(), play_message_datetime(), prep_email_sub_vars(), rt_extend_conf(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), set_timezone_variables(), sip_show_registry(), sms_compose2(), sms_handleincoming_proto2(), static_callback(), timeout_write(), transmit_definetimedate(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().

01571 {
01572    const struct state *sp = ast_tzset(zone);
01573    memset(tmp, 0, sizeof(*tmp));
01574    return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01575 }

void ast_localtime_wakeup_monitor ( struct ast_test *  info  ) 

Definition at line 607 of file localtime.c.

References ast_cond_wait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, and lock.

00608 {
00609    if (inotify_thread != AST_PTHREADT_NULL) {
00610       AST_LIST_LOCK(&zonelist);
00611 #ifdef TEST_FRAMEWORK
00612       test = info;
00613 #endif
00614       pthread_kill(inotify_thread, SIGURG);
00615       ast_cond_wait(&initialization, &(&zonelist)->lock);
00616 #ifdef TEST_FRAMEWORK
00617       test = NULL;
00618 #endif
00619       AST_LIST_UNLOCK(&zonelist);
00620    }
00621 }

struct timeval ast_mktime ( struct ast_tm *const   tmp,
const char *  zone 
) [read]

Timezone-independent version of mktime(3).

Parameters:
tmp Current broken-out time, including microseconds
zone Text string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
A structure containing both seconds and fractional thereof since January 1st, 1970 UTC

Definition at line 2185 of file localtime.c.

References ast_tzset(), localsub(), and time1().

Referenced by acf_strptime(), conf_run(), find_conf_realtime(), icalfloat_to_timet(), mstime_to_time_t(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), testtime_write(), and unpackdate().

02186 {
02187    const struct state *sp;
02188    if (!(sp = ast_tzset(zone)))
02189       return WRONG;
02190    return time1(tmp, localsub, 0L, sp);
02191 }

const char* ast_setlocale ( const char *  locale  ) 

Set the thread-local representation of the current locale.

Definition at line 2248 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_name(), locale_entry::locale, locale_entry::name, and store_by_locale().

Referenced by ast_strftime_locale(), and ast_strptime_locale().

02249 {
02250    struct locale_entry *cur;
02251    locale_t prevlocale = LC_GLOBAL_LOCALE;
02252 
02253    if (locale == NULL) {
02254       return store_by_locale(uselocale(LC_GLOBAL_LOCALE));
02255    }
02256 
02257    AST_LIST_LOCK(&localelist);
02258    if ((cur = find_by_name(locale))) {
02259       prevlocale = uselocale(cur->locale);
02260    }
02261 
02262    if (!cur) {
02263       if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) {
02264          cur->locale = newlocale(LC_ALL_MASK, locale, NULL);
02265          strcpy(cur->name, locale); /* SAFE */
02266          AST_LIST_INSERT_TAIL(&localelist, cur, list);
02267          prevlocale = uselocale(cur->locale);
02268       }
02269    }
02270    AST_LIST_UNLOCK(&localelist);
02271    return store_by_locale(prevlocale);
02272 }

int ast_strftime ( char *  buf,
size_t  len,
const char *  format,
const struct ast_tm tm 
)

Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds.

Parameters:
buf Address in memory where the resulting string will be stored.
len Size of the chunk of memory buf.
format A string specifying the format of time to be placed into buf.
tm Pointer to the broken out time to be used for the format.
locale Text string specifying the locale to be used for language strings.
Return values:
An integer value specifying the number of bytes placed into buf or -1 on error.

Definition at line 2351 of file localtime.c.

References ast_strftime_locale().

Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_log(), ast_queue_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), conf_run(), dump_datetime(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), isodate(), leave_voicemail(), make_email_file(), manager_log(), mstime(), odbc_log(), pgsql_log(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().

02352 {
02353    return ast_strftime_locale(buf, len, tmp, tm, NULL);
02354 }

int ast_strftime_locale ( char *  buf,
size_t  len,
const char *  tmp,
const struct ast_tm tm,
const char *  locale 
)

Definition at line 2280 of file localtime.c.

References ast_calloc, ast_free, ast_realloc, ast_setlocale(), format, and ast_tm::tm_usec.

Referenced by ast_strftime(), make_email_file(), prep_email_sub_vars(), and sendpage().

02281 {
02282    size_t fmtlen = strlen(tmp) + 1;
02283    char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
02284    int decimals = -1, i, res;
02285    long fraction;
02286    const char *prevlocale;
02287 
02288    if (!format) {
02289       return -1;
02290    }
02291    for (; *tmp; tmp++) {
02292       if (*tmp == '%') {
02293          switch (tmp[1]) {
02294          case '1':
02295          case '2':
02296          case '3':
02297          case '4':
02298          case '5':
02299          case '6':
02300             if (tmp[2] != 'q') {
02301                goto defcase;
02302             }
02303             decimals = tmp[1] - '0';
02304             tmp++;
02305             /* Fall through */
02306          case 'q': /* Milliseconds */
02307             if (decimals == -1) {
02308                decimals = 3;
02309             }
02310 
02311             /* Juggle some memory to fit the item */
02312             newfmt = ast_realloc(format, fmtlen + decimals);
02313             if (!newfmt) {
02314                ast_free(format);
02315                return -1;
02316             }
02317             fptr = fptr - format + newfmt;
02318             format = newfmt;
02319             fmtlen += decimals;
02320 
02321             /* Reduce the fraction of time to the accuracy needed */
02322             for (i = 6, fraction = tm->tm_usec; i > decimals; i--) {
02323                fraction /= 10;
02324             }
02325             fptr += sprintf(fptr, "%0*ld", decimals, fraction);
02326 
02327             /* Reset, in case more than one 'q' specifier exists */
02328             decimals = -1;
02329             tmp++;
02330             break;
02331          default:
02332             goto defcase;
02333          }
02334       } else {
02335 defcase: *fptr++ = *tmp;
02336       }
02337    }
02338    *fptr = '\0';
02339 #undef strftime
02340    if (locale) {
02341       prevlocale = ast_setlocale(locale);
02342    }
02343    res = (int)strftime(buf, len, format, (struct tm *)tm);
02344    if (locale) {
02345       ast_setlocale(prevlocale);
02346    }
02347    ast_free(format);
02348    return res;
02349 }

char* ast_strptime ( const char *  s,
const char *  format,
struct ast_tm tm 
)

Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.

Parameters:
s A string specifying some portion of a date and time.
format The format in which the string, s, is expected.
tm The broken-out time structure into which the parsed data is expected.
locale Text string specifying the locale to be used for language strings.
Return values:
A pointer to the first character within s not used to parse the date and time.

Definition at line 2377 of file localtime.c.

References ast_strptime_locale().

Referenced by acf_strptime(), conf_run(), find_conf_realtime(), mstime_to_time_t(), rt_extend_conf(), and testtime_write().

02378 {
02379    return ast_strptime_locale(s, format, tm, NULL);
02380 }

char* ast_strptime_locale ( const char *  s,
const char *  format,
struct ast_tm tm,
const char *  locale 
)

Definition at line 2356 of file localtime.c.

References ast_setlocale(), ast_tm::tm_isdst, and ast_tm::tm_usec.

Referenced by ast_strptime().

02357 {
02358    struct tm tm2 = { 0, };
02359    char *res;
02360    const char *prevlocale;
02361 
02362    prevlocale = ast_setlocale(locale);
02363    res = strptime(s, format, &tm2);
02364    ast_setlocale(prevlocale);
02365    /* ast_time and tm are not the same size - tm is a subset of
02366     * ast_time.  Hence, the size of tm needs to be used for the
02367     * memcpy
02368     */
02369    memcpy(tm, &tm2, sizeof(tm2));
02370    tm->tm_usec = 0;
02371    /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
02372     * to deal with it correctly, we set it to -1. */
02373    tm->tm_isdst = -1;
02374    return res;
02375 }

static struct state* ast_tzset ( const char *  zone  )  [static, read]

Definition at line 1432 of file localtime.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), FALSE, gmtload(), state::name, TRUE, tzload(), and tzparse().

Referenced by ast_get_dst_info(), ast_localtime(), and ast_mktime().

01433 {
01434    struct state *sp;
01435 
01436    if (ast_strlen_zero(zone)) {
01437 #ifdef SOLARIS
01438       zone = getenv("TZ");
01439       if (ast_strlen_zero(zone)) {
01440          zone = "GMT";
01441       }
01442 #else
01443       zone = "/etc/localtime";
01444 #endif
01445    }
01446 
01447    AST_LIST_LOCK(&zonelist);
01448    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01449       if (!strcmp(sp->name, zone)) {
01450          AST_LIST_UNLOCK(&zonelist);
01451          return sp;
01452       }
01453    }
01454    AST_LIST_UNLOCK(&zonelist);
01455 
01456    if (!(sp = ast_calloc(1, sizeof *sp)))
01457       return NULL;
01458 
01459    if (tzload(zone, sp, TRUE) != 0) {
01460       if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
01461          (void) gmtload(sp);
01462    }
01463    ast_copy_string(sp->name, zone, sizeof(sp->name));
01464    AST_LIST_LOCK(&zonelist);
01465    AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01466    AST_LIST_UNLOCK(&zonelist);
01467    return sp;
01468 }

void clean_time_zones ( void   ) 

Provided by localtime.c

Definition at line 1421 of file localtime.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by really_quit().

01422 {
01423    struct state *sp;
01424 
01425    AST_LIST_LOCK(&zonelist);
01426    while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
01427       ast_free(sp);
01428    }
01429    AST_LIST_UNLOCK(&zonelist);
01430 }

static long detzcode ( const char *const   codep  )  [static]
Note:
Section 4.12.3 of X3.159-1989 requires that Except for the strftime function, these functions [asctime, ctime, gmtime, localtime] return values in one of two static objects: a broken-down time structure and an array of char. Thanks to Paul Eggert for noting this.

Definition at line 631 of file localtime.c.

Referenced by tzload().

00632 {
00633    long  result;
00634    int   i;
00635 
00636    result = (codep[0] & 0x80) ? ~0L : 0;
00637    for (i = 0; i < 4; ++i)
00638       result = (result << 8) | (codep[i] & 0xff);
00639    return result;
00640 }

static time_t detzcode64 ( const char *const   codep  )  [static]

Definition at line 642 of file localtime.c.

References int_fast64_t.

Referenced by tzload().

00643 {
00644    time_t   result;
00645    int   i;
00646 
00647    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00648    for (i = 0; i < 8; ++i)
00649       result = result * 256 + (codep[i] & 0xff);
00650    return result;
00651 }

static int differ_by_repeat ( const time_t  t1,
const time_t  t0 
) [static]

Definition at line 653 of file localtime.c.

References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.

Referenced by tzload().

00654 {
00655    const long long at1 = t1, at0 = t0;
00656    if (TYPE_INTEGRAL(time_t) &&
00657       TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00658          return 0;
00659    return at1 - at0 == SECSPERREPEAT;
00660 }

static struct locale_entry* find_by_locale ( locale_t  locale  )  [static, read]

Definition at line 2194 of file localtime.c.

References AST_LIST_TRAVERSE, and locale_entry::locale.

Referenced by store_by_locale().

02195 {
02196    struct locale_entry *cur;
02197    AST_LIST_TRAVERSE(&localelist, cur, list) {
02198       if (locale == cur->locale) {
02199          return cur;
02200       }
02201    }
02202    return NULL;
02203 }

static struct locale_entry* find_by_name ( const char *  name  )  [static, read]

Definition at line 2205 of file localtime.c.

References AST_LIST_TRAVERSE, and locale_entry::name.

Referenced by ast_setlocale(), and store_by_locale().

02206 {
02207    struct locale_entry *cur;
02208    AST_LIST_TRAVERSE(&localelist, cur, list) {
02209       if (strcmp(name, cur->name) == 0) {
02210          return cur;
02211       }
02212    }
02213    return NULL;
02214 }

static const char* getnum ( const char *  strp,
int *  nump,
const int  min,
const int  max 
) [static]

Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.

Definition at line 950 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

00951 {
00952    char  c;
00953    int   num;
00954 
00955    if (strp == NULL || !is_digit(c = *strp))
00956       return NULL;
00957    num = 0;
00958    do {
00959       num = num * 10 + (c - '0');
00960       if (num > max)
00961          return NULL;   /* illegal value */
00962       c = *++strp;
00963    } while (is_digit(c));
00964    if (num < min)
00965       return NULL;      /* illegal value */
00966    *nump = num;
00967    return strp;
00968 }

static const char* getoffset ( const char *  strp,
long *  offsetp 
) [static]

Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.

Definition at line 1017 of file localtime.c.

References getsecs().

Referenced by tzparse().

01018 {
01019    int   neg = 0;
01020 
01021    if (*strp == '-') {
01022       neg = 1;
01023       ++strp;
01024    } else if (*strp == '+')
01025       ++strp;
01026    strp = getsecs(strp, offsetp);
01027    if (strp == NULL)
01028       return NULL;      /* illegal time */
01029    if (neg)
01030       *offsetp = -*offsetp;
01031    return strp;
01032 }

static const char* getqzname ( const char *  strp,
const int  delim 
) [static]

Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.

As with getzname above, the legal character set is actually quite restricted, with other characters producing undefined results. We don't do any checking here; checking is done later in common-case code.

Definition at line 934 of file localtime.c.

Referenced by tzparse().

00935 {
00936    int   c;
00937 
00938    while ((c = *strp) != '\0' && c != delim)
00939       ++strp;
00940    return strp;
00941 }

static const char* getrule ( const char *  strp,
struct rule rulep 
) [static]

Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.

Definition at line 1041 of file localtime.c.

References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.

Referenced by tzparse().

01042 {
01043    if (*strp == 'J') {
01044       /*
01045       ** Julian day.
01046       */
01047       rulep->r_type = JULIAN_DAY;
01048       ++strp;
01049       strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
01050    } else if (*strp == 'M') {
01051       /*
01052       ** Month, week, day.
01053       */
01054       rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
01055       ++strp;
01056       strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
01057       if (strp == NULL)
01058          return NULL;
01059       if (*strp++ != '.')
01060          return NULL;
01061       strp = getnum(strp, &rulep->r_week, 1, 5);
01062       if (strp == NULL)
01063          return NULL;
01064       if (*strp++ != '.')
01065          return NULL;
01066       strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
01067    } else if (is_digit(*strp)) {
01068       /*
01069       ** Day of year.
01070       */
01071       rulep->r_type = DAY_OF_YEAR;
01072       strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
01073    } else   return NULL;      /* invalid format */
01074    if (strp == NULL)
01075       return NULL;
01076    if (*strp == '/') {
01077       /*
01078       ** Time specified.
01079       */
01080       ++strp;
01081       strp = getsecs(strp, &rulep->r_time);
01082    } else   rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
01083    return strp;
01084 }

static const char* getsecs ( const char *  strp,
long *const   secsp 
) [static]

Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.

Definition at line 978 of file localtime.c.

References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.

Referenced by getoffset(), and getrule().

00979 {
00980    int   num;
00981 
00982    /*
00983    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00984    ** "M10.4.6/26", which does not conform to Posix,
00985    ** but which specifies the equivalent of
00986    ** ``02:00 on the first Sunday on or after 23 Oct''.
00987    */
00988    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00989    if (strp == NULL)
00990       return NULL;
00991    *secsp = num * (long) SECSPERHOUR;
00992    if (*strp == ':') {
00993       ++strp;
00994       strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00995       if (strp == NULL)
00996          return NULL;
00997       *secsp += num * SECSPERMIN;
00998       if (*strp == ':') {
00999          ++strp;
01000          /* `SECSPERMIN' allows for leap seconds. */
01001          strp = getnum(strp, &num, 0, SECSPERMIN);
01002          if (strp == NULL)
01003             return NULL;
01004          *secsp += num;
01005       }
01006    }
01007    return strp;
01008 }

static const char* getzname ( const char *  strp  )  [static]

Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.

Definition at line 915 of file localtime.c.

References is_digit.

Referenced by tzparse().

00916 {
00917    char  c;
00918 
00919    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00920       c != '+')
00921          ++strp;
00922    return strp;
00923 }

static int gmtload ( struct state sp  )  [static]

Definition at line 1413 of file localtime.c.

References TRUE, tzload(), and tzparse().

Referenced by ast_tzset(), and gmtsub().

01414 {
01415    if (tzload(gmt, sp, TRUE) != 0)
01416       return tzparse(gmt, sp, TRUE);
01417    else
01418       return -1;
01419 }

static struct ast_tm* gmtsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp 
) [static, read]

Definition at line 1696 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::name, and timesub().

Referenced by localsub().

01697 {
01698    struct ast_tm *   result;
01699    struct state *sp;
01700 
01701    AST_LIST_LOCK(&zonelist);
01702    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01703       if (!strcmp(sp->name, "UTC"))
01704          break;
01705    }
01706 
01707    if (!sp) {
01708       if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01709          return NULL;
01710       gmtload(sp);
01711       AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01712    }
01713    AST_LIST_UNLOCK(&zonelist);
01714 
01715    result = timesub(timep, offset, sp, tmp);
01716 #ifdef TM_ZONE
01717    /*
01718    ** Could get fancy here and deliver something such as
01719    ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
01720    ** but this is no time for a treasure hunt.
01721    */
01722    if (offset != 0)
01723       tmp->TM_ZONE = "    ";
01724    else
01725       tmp->TM_ZONE = sp->chars;
01726 #endif /* defined TM_ZONE */
01727    return result;
01728 }

static int increment_overflow ( int *  number,
int  delta 
) [static]

Simplified normalize logic courtesy Paul Eggert.

Note:
Adapted from code provided by Robert Elz, who writes: The "best" way to do mktime I think is based on an idea of Bob Kridle's (so its said...) from a long time ago. It does a binary search of the time_t space. Since time_t's are just 32 bits, its a max of 32 iterations (even at 64 bits it would still be very reasonable).

Definition at line 1879 of file localtime.c.

Referenced by normalize_overflow(), time2sub(), and timesub().

01880 {
01881    int   number0;
01882 
01883    number0 = *number;
01884    *number += delta;
01885    return (*number < number0) != (delta < 0);
01886 }

static void* inotify_daemon ( void *  data  )  [static]

Definition at line 272 of file localtime.c.

References ast_cond_broadcast, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, errno, FILENAME_MAX, LOG_ERROR, state::name, and state::wd.

Referenced by add_notify().

00273 {
00274    struct {
00275       struct inotify_event iev;
00276       char name[FILENAME_MAX + 1];
00277    } buf;
00278    ssize_t res;
00279    struct state *cur;
00280 
00281    inotify_fd = inotify_init();
00282 
00283    ast_mutex_lock(&initialization_lock);
00284    ast_cond_broadcast(&initialization);
00285    ast_mutex_unlock(&initialization_lock);
00286 
00287    if (inotify_fd < 0) {
00288       ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
00289       inotify_thread = AST_PTHREADT_NULL;
00290       return NULL;
00291    }
00292 
00293    for (;/*ever*/;) {
00294       /* This read should block, most of the time. */
00295       if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
00296          /* This should never happen */
00297          ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zu)?!!\n", res, sizeof(buf.iev));
00298          break;
00299       } else if (res < 0) {
00300          if (errno == EINTR || errno == EAGAIN) {
00301             /* If read fails, try again */
00302             AST_LIST_LOCK(&zonelist);
00303             ast_cond_broadcast(&initialization);
00304             AST_LIST_UNLOCK(&zonelist);
00305             continue;
00306          }
00307          /* Sanity check -- this should never happen, either */
00308          ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
00309          break;
00310       }
00311       AST_LIST_LOCK(&zonelist);
00312       AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
00313          if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
00314             AST_LIST_REMOVE_CURRENT(list);
00315             ast_free(cur);
00316             break;
00317          }
00318       }
00319       AST_LIST_TRAVERSE_SAFE_END
00320       ast_cond_broadcast(&initialization);
00321       AST_LIST_UNLOCK(&zonelist);
00322    }
00323    close(inotify_fd);
00324    inotify_thread = AST_PTHREADT_NULL;
00325    return NULL;
00326 }

static int leaps_thru_end_of ( const int  y  )  [static]

Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.

Definition at line 1735 of file localtime.c.

Referenced by timesub().

01736 {
01737    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01738       -(leaps_thru_end_of(-(y + 1)) + 1);
01739 }

static struct ast_tm* localsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp,
const struct state sp 
) [static, read]
Note:
The easy way to behave "as if no library function calls" localtime is to not call it--so we drop its guts into "localsub", which can be freely called. (And no, the PANS doesn't require the above behavior-- but it *is* desirable.)

The unused offset argument is for the benefit of mktime variants.

Definition at line 1479 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, int_fast64_t, state::timecnt, timesub(), ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, ast_tm::tm_year, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by ast_localtime(), and ast_mktime().

01480 {
01481    const struct ttinfo *   ttisp;
01482    int         i;
01483    struct ast_tm *      result;
01484    struct timeval t;
01485    memcpy(&t, timep, sizeof(t));
01486 
01487    if (sp == NULL)
01488       return gmtsub(timep, offset, tmp);
01489    if ((sp->goback && t.tv_sec < sp->ats[0]) ||
01490       (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
01491          struct timeval newt = t;
01492          time_t      seconds;
01493          time_t      tcycles;
01494          int_fast64_t   icycles;
01495 
01496          if (t.tv_sec < sp->ats[0])
01497             seconds = sp->ats[0] - t.tv_sec;
01498          else  seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
01499          --seconds;
01500          tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01501          ++tcycles;
01502          icycles = tcycles;
01503          if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01504             return NULL;
01505          seconds = icycles;
01506          seconds *= YEARSPERREPEAT;
01507          seconds *= AVGSECSPERYEAR;
01508          if (t.tv_sec < sp->ats[0])
01509             newt.tv_sec += seconds;
01510          else  newt.tv_sec -= seconds;
01511          if (newt.tv_sec < sp->ats[0] ||
01512             newt.tv_sec > sp->ats[sp->timecnt - 1])
01513                return NULL;   /* "cannot happen" */
01514          result = localsub(&newt, offset, tmp, sp);
01515          if (result == tmp) {
01516             time_t   newy;
01517 
01518             newy = tmp->tm_year;
01519             if (t.tv_sec < sp->ats[0])
01520                newy -= icycles * YEARSPERREPEAT;
01521             else
01522                newy += icycles * YEARSPERREPEAT;
01523             tmp->tm_year = newy;
01524             if (tmp->tm_year != newy)
01525                return NULL;
01526          }
01527          return result;
01528    }
01529    if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
01530       i = 0;
01531       while (sp->ttis[i].tt_isdst) {
01532          if (++i >= sp->typecnt) {
01533             i = 0;
01534             break;
01535          }
01536       }
01537    } else {
01538       int   lo = 1;
01539       int   hi = sp->timecnt;
01540 
01541       while (lo < hi) {
01542          int   mid = (lo + hi) >> 1;
01543 
01544          if (t.tv_sec < sp->ats[mid])
01545             hi = mid;
01546          else
01547             lo = mid + 1;
01548       }
01549       i = (int) sp->types[lo - 1];
01550    }
01551    ttisp = &sp->ttis[i];
01552    /*
01553    ** To get (wrong) behavior that's compatible with System V Release 2.0
01554    ** you'd replace the statement below with
01555    ** t += ttisp->tt_gmtoff;
01556    ** timesub(&t, 0L, sp, tmp);
01557    */
01558    result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01559    tmp->tm_isdst = ttisp->tt_isdst;
01560 #ifndef SOLARIS /* Solaris doesn't have this element */
01561    tmp->tm_gmtoff = ttisp->tt_gmtoff;
01562 #endif
01563 #ifdef TM_ZONE
01564    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01565 #endif /* defined TM_ZONE */
01566    tmp->tm_usec = timep->tv_usec;
01567    return result;
01568 }

static int long_increment_overflow ( long *  number,
int  delta 
) [static]

Definition at line 1888 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

01889 {
01890    long  number0;
01891 
01892    number0 = *number;
01893    *number += delta;
01894    return (*number < number0) != (delta < 0);
01895 }

static int long_normalize_overflow ( long *  tensptr,
int *  unitsptr,
const int  base 
) [static]

Definition at line 1908 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

01909 {
01910    int   tensdelta;
01911 
01912    tensdelta = (*unitsptr >= 0) ?
01913       (*unitsptr / base) :
01914       (-1 - (-1 - *unitsptr) / base);
01915    *unitsptr -= tensdelta * base;
01916    return long_increment_overflow(tensptr, tensdelta);
01917 }

static int normalize_overflow ( int *  tensptr,
int *  unitsptr,
const int  base 
) [static]

Definition at line 1897 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

01898 {
01899    int   tensdelta;
01900 
01901    tensdelta = (*unitsptr >= 0) ?
01902       (*unitsptr / base) :
01903       (-1 - (-1 - *unitsptr) / base);
01904    *unitsptr -= tensdelta * base;
01905    return increment_overflow(tensptr, tensdelta);
01906 }

static int tzparse P ( (const char *name, struct state *sp, int lastditch)   )  [static]
static int tzload P ( (const char *name, struct state *sp, int doextend)   )  [static]
static time_t transtime P ( (time_t janfirst, int year, const struct rule *rulep, long offset)   )  [static]
static int tmcomp P ( (const struct ast_tm *atmp, const struct ast_tm *btmp)   )  [static]
static struct ast_tm* timesub P ( (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp)   )  [static, read]
static struct timeval time2sub P ( (struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp)   )  [static, read]
static struct timeval time2 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)   )  [static, read]
static struct timeval time1 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp)   )  [static, read]
static int normalize_overflow P ( (int *tensptr, int *unitsptr, const int base)   )  [static]
static int long_normalize_overflow P ( (long *tensptr, int *unitsptr, const int base)   )  [static]
static int long_increment_overflow P ( (long *number, int delta)   )  [static]
static int leaps_thru_end_of P ( (int y)   )  [static]
static int increment_overflow P ( (int *number, int delta)   )  [static]
static struct ast_tm* localsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp)   )  [static, read]
static struct ast_tm* gmtsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp)   )  [static, read]
static int gmtload P ( (struct state *sp)   )  [static]
static const char* getrule P ( (const char *strp, struct rule *rulep)   )  [static]
static const char* getoffset P ( (const char *strp, long *offsetp)   )  [static]
static const char* getsecs P ( (const char *strp, long *secsp)   )  [static]
static const char* getnum P ( (const char *strp, int *nump, int min, int max)   )  [static]
static const char* getqzname P ( (const char *strp, const int delim)   )  [static]
static const char* getzname P ( (const char *strp)   )  [static]
static int differ_by_repeat P ( (time_t t1, time_t t0)   )  [static]
static time_t detzcode64 P ( (const char *codep)   )  [static]
static const char* store_by_locale ( locale_t  prevlocale  )  [static]

Definition at line 2216 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_locale(), find_by_name(), locale_entry::locale, and locale_entry::name.

Referenced by ast_setlocale().

02217 {
02218    struct locale_entry *cur;
02219    if (prevlocale == LC_GLOBAL_LOCALE) {
02220       return NULL;
02221    } else {
02222       /* Get a handle for this entry, if any */
02223       if ((cur = find_by_locale(prevlocale))) {
02224          return cur->name;
02225       } else {
02226          /* Create an entry, so it can be restored later */
02227          int x;
02228          cur = NULL;
02229          AST_LIST_LOCK(&localelist);
02230          for (x = 0; x < 10000; x++) {
02231             char name[5];
02232             snprintf(name, sizeof(name), "%04d", x);
02233             if (!find_by_name(name)) {
02234                if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) {
02235                   cur->locale = prevlocale;
02236                   strcpy(cur->name, name); /* SAFE */
02237                   AST_LIST_INSERT_TAIL(&localelist, cur, list);
02238                }
02239                break;
02240             }
02241          }
02242          AST_LIST_UNLOCK(&localelist);
02243          return cur ? cur->name : NULL;
02244       }
02245    }
02246 }

static struct timeval time1 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
const struct state sp 
) [static, read]

Definition at line 2120 of file localtime.c.

References FALSE, time2(), state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and TZ_MAX_TYPES.

Referenced by ast_mktime().

02121 {
02122    struct timeval       t;
02123    int         samei, otheri;
02124    int         sameind, otherind;
02125    int         i;
02126    int         nseen;
02127    int            seen[TZ_MAX_TYPES];
02128    int            types[TZ_MAX_TYPES];
02129    int            okay;
02130 
02131    if (tmp->tm_isdst > 1)
02132       tmp->tm_isdst = 1;
02133    t = time2(tmp, funcp, offset, &okay, sp);
02134 #ifdef PCTS
02135    /*
02136    ** PCTS code courtesy Grant Sullivan.
02137    */
02138    if (okay)
02139       return t;
02140    if (tmp->tm_isdst < 0)
02141       tmp->tm_isdst = 0;   /* reset to std and try again */
02142 #endif /* defined PCTS */
02143 #ifndef PCTS
02144    if (okay || tmp->tm_isdst < 0)
02145       return t;
02146 #endif /* !defined PCTS */
02147    /*
02148    ** We're supposed to assume that somebody took a time of one type
02149    ** and did some math on it that yielded a "struct ast_tm" that's bad.
02150    ** We try to divine the type they started from and adjust to the
02151    ** type they need.
02152    */
02153    if (sp == NULL)
02154       return WRONG;
02155    for (i = 0; i < sp->typecnt; ++i)
02156       seen[i] = FALSE;
02157    nseen = 0;
02158    for (i = sp->timecnt - 1; i >= 0; --i)
02159       if (!seen[sp->types[i]]) {
02160          seen[sp->types[i]] = TRUE;
02161          types[nseen++] = sp->types[i];
02162       }
02163    for (sameind = 0; sameind < nseen; ++sameind) {
02164       samei = types[sameind];
02165       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
02166          continue;
02167       for (otherind = 0; otherind < nseen; ++otherind) {
02168          otheri = types[otherind];
02169          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
02170             continue;
02171          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
02172                sp->ttis[samei].tt_gmtoff;
02173          tmp->tm_isdst = !tmp->tm_isdst;
02174          t = time2(tmp, funcp, offset, &okay, sp);
02175          if (okay)
02176             return t;
02177          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
02178                sp->ttis[samei].tt_gmtoff;
02179          tmp->tm_isdst = !tmp->tm_isdst;
02180       }
02181    }
02182    return WRONG;
02183 }

static struct timeval time2 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp)  funcp,
const long  offset,
int *  okayp,
const struct state sp 
) [static, read]

Note:
First try without normalization of seconds (in case tm_sec contains a value associated with a leap second). If that fails, try with normalization of seconds.

Definition at line 2107 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

02108 {
02109    struct timeval t;
02110 
02111    /*! \note
02112    ** First try without normalization of seconds
02113    ** (in case tm_sec contains a value associated with a leap second).
02114    ** If that fails, try with normalization of seconds.
02115    */
02116    t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
02117    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
02118 }

static struct timeval time2sub ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
int *  okayp,
const int  do_norm_secs,
const struct state sp 
) [static, read]

Definition at line 1933 of file localtime.c.

References DAYSPERLYEAR, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, tmcomp(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, and state::typecnt.

Referenced by time2().

01934 {
01935    int         dir;
01936    int         i, j;
01937    int         saved_seconds;
01938    long        li;
01939    time_t         lo;
01940    time_t         hi;
01941    long           y;
01942    struct timeval       newt = { 0, 0 };
01943    struct timeval       t = { 0, 0 };
01944    struct ast_tm        yourtm, mytm;
01945 
01946    *okayp = FALSE;
01947    yourtm = *tmp;
01948    if (do_norm_secs) {
01949       if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01950          SECSPERMIN))
01951             return WRONG;
01952    }
01953    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01954       return WRONG;
01955    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01956       return WRONG;
01957    y = yourtm.tm_year;
01958    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01959       return WRONG;
01960    /*
01961    ** Turn y into an actual year number for now.
01962    ** It is converted back to an offset from TM_YEAR_BASE later.
01963    */
01964    if (long_increment_overflow(&y, TM_YEAR_BASE))
01965       return WRONG;
01966    while (yourtm.tm_mday <= 0) {
01967       if (long_increment_overflow(&y, -1))
01968          return WRONG;
01969       li = y + (1 < yourtm.tm_mon);
01970       yourtm.tm_mday += year_lengths[isleap(li)];
01971    }
01972    while (yourtm.tm_mday > DAYSPERLYEAR) {
01973       li = y + (1 < yourtm.tm_mon);
01974       yourtm.tm_mday -= year_lengths[isleap(li)];
01975       if (long_increment_overflow(&y, 1))
01976          return WRONG;
01977    }
01978    for ( ; ; ) {
01979       i = mon_lengths[isleap(y)][yourtm.tm_mon];
01980       if (yourtm.tm_mday <= i)
01981          break;
01982       yourtm.tm_mday -= i;
01983       if (++yourtm.tm_mon >= MONSPERYEAR) {
01984          yourtm.tm_mon = 0;
01985          if (long_increment_overflow(&y, 1))
01986             return WRONG;
01987       }
01988    }
01989    if (long_increment_overflow(&y, -TM_YEAR_BASE))
01990       return WRONG;
01991    yourtm.tm_year = y;
01992    if (yourtm.tm_year != y)
01993       return WRONG;
01994    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01995       saved_seconds = 0;
01996    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01997       /*
01998       ** We can't set tm_sec to 0, because that might push the
01999       ** time below the minimum representable time.
02000       ** Set tm_sec to 59 instead.
02001       ** This assumes that the minimum representable time is
02002       ** not in the same minute that a leap second was deleted from,
02003       ** which is a safer assumption than using 58 would be.
02004       */
02005       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
02006          return WRONG;
02007       saved_seconds = yourtm.tm_sec;
02008       yourtm.tm_sec = SECSPERMIN - 1;
02009    } else {
02010       saved_seconds = yourtm.tm_sec;
02011       yourtm.tm_sec = 0;
02012    }
02013    /*
02014    ** Do a binary search (this works whatever time_t's type is).
02015    */
02016    if (!TYPE_SIGNED(time_t)) {
02017       lo = 0;
02018       hi = lo - 1;
02019    } else if (!TYPE_INTEGRAL(time_t)) {
02020       if (sizeof(time_t) > sizeof(float))
02021          hi = (time_t) DBL_MAX;
02022       else  hi = (time_t) FLT_MAX;
02023       lo = -hi;
02024    } else {
02025       lo = 1;
02026       for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
02027          lo *= 2;
02028       hi = -(lo + 1);
02029    }
02030    for ( ; ; ) {
02031       t.tv_sec = lo / 2 + hi / 2;
02032       if (t.tv_sec < lo)
02033          t.tv_sec = lo;
02034       else if (t.tv_sec > hi)
02035          t.tv_sec = hi;
02036       if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
02037          /*
02038          ** Assume that t is too extreme to be represented in
02039          ** a struct ast_tm; arrange things so that it is less
02040          ** extreme on the next pass.
02041          */
02042          dir = (t.tv_sec > 0) ? 1 : -1;
02043       } else   dir = tmcomp(&mytm, &yourtm);
02044       if (dir != 0) {
02045          if (t.tv_sec == lo) {
02046             ++t.tv_sec;
02047             if (t.tv_sec <= lo)
02048                return WRONG;
02049             ++lo;
02050          } else if (t.tv_sec == hi) {
02051             --t.tv_sec;
02052             if (t.tv_sec >= hi)
02053                return WRONG;
02054             --hi;
02055          }
02056          if (lo > hi)
02057             return WRONG;
02058          if (dir > 0)
02059             hi = t.tv_sec;
02060          else  lo = t.tv_sec;
02061          continue;
02062       }
02063       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
02064          break;
02065       /*
02066       ** Right time, wrong type.
02067       ** Hunt for right time, right type.
02068       ** It's okay to guess wrong since the guess
02069       ** gets checked.
02070       */
02071       /*
02072       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
02073       */
02074       for (i = sp->typecnt - 1; i >= 0; --i) {
02075          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
02076             continue;
02077          for (j = sp->typecnt - 1; j >= 0; --j) {
02078             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
02079                continue;
02080             newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
02081                sp->ttis[i].tt_gmtoff;
02082             if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
02083                continue;
02084             if (tmcomp(&mytm, &yourtm) != 0)
02085                continue;
02086             if (mytm.tm_isdst != yourtm.tm_isdst)
02087                continue;
02088             /*
02089             ** We have a match.
02090             */
02091             t = newt;
02092             goto label;
02093          }
02094       }
02095       return WRONG;
02096    }
02097 label:
02098    newt.tv_sec = t.tv_sec + saved_seconds;
02099    if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
02100       return WRONG;
02101    t.tv_sec = newt.tv_sec;
02102    if ((*funcp)(&t, offset, tmp, sp))
02103       *okayp = TRUE;
02104    return t;
02105 }

static struct ast_tm* timesub ( const struct timeval *  timep,
const long  offset,
const struct state sp,
struct ast_tm tmp 
) [static, read]

Definition at line 1741 of file localtime.c.

References DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, SECSPERDAY, SECSPERHOUR, SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_yday, ast_tm::tm_year, and TM_YEAR_BASE.

Referenced by gmtsub(), and localsub().

01742 {
01743    const struct lsinfo *   lp;
01744    time_t         tdays;
01745    int         idays;   /* unsigned would be so 2003 */
01746    long        rem;
01747    int            y;
01748    const int *    ip;
01749    long        corr;
01750    int         hit;
01751    int         i;
01752    long  seconds;
01753 
01754 
01755    corr = 0;
01756    hit = 0;
01757    i = (sp == NULL) ? 0 : sp->leapcnt;
01758    while (--i >= 0) {
01759       lp = &sp->lsis[i];
01760       if (timep->tv_sec >= lp->ls_trans) {
01761          if (timep->tv_sec == lp->ls_trans) {
01762             hit = ((i == 0 && lp->ls_corr > 0) ||
01763                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01764             if (hit)
01765                while (i > 0 &&
01766                   sp->lsis[i].ls_trans ==
01767                   sp->lsis[i - 1].ls_trans + 1 &&
01768                   sp->lsis[i].ls_corr ==
01769                   sp->lsis[i - 1].ls_corr + 1) {
01770                      ++hit;
01771                      --i;
01772                }
01773          }
01774          corr = lp->ls_corr;
01775          break;
01776       }
01777    }
01778    y = EPOCH_YEAR;
01779    tdays = timep->tv_sec / SECSPERDAY;
01780    rem = timep->tv_sec - tdays * SECSPERDAY;
01781    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01782       int      newy;
01783       time_t   tdelta;
01784       int   idelta;
01785       int   leapdays;
01786 
01787       tdelta = tdays / DAYSPERLYEAR;
01788       idelta = tdelta;
01789       if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01790          return NULL;
01791       if (idelta == 0)
01792          idelta = (tdays < 0) ? -1 : 1;
01793       newy = y;
01794       if (increment_overflow(&newy, idelta))
01795          return NULL;
01796       leapdays = leaps_thru_end_of(newy - 1) -
01797          leaps_thru_end_of(y - 1);
01798       tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01799       tdays -= leapdays;
01800       y = newy;
01801    }
01802 
01803    seconds = tdays * SECSPERDAY + 0.5;
01804    tdays = seconds / SECSPERDAY;
01805    rem += seconds - tdays * SECSPERDAY;
01806 
01807    /*
01808    ** Given the range, we can now fearlessly cast...
01809    */
01810    idays = tdays;
01811    rem += offset - corr;
01812    while (rem < 0) {
01813       rem += SECSPERDAY;
01814       --idays;
01815    }
01816    while (rem >= SECSPERDAY) {
01817       rem -= SECSPERDAY;
01818       ++idays;
01819    }
01820    while (idays < 0) {
01821       if (increment_overflow(&y, -1))
01822          return NULL;
01823       idays += year_lengths[isleap(y)];
01824    }
01825    while (idays >= year_lengths[isleap(y)]) {
01826       idays -= year_lengths[isleap(y)];
01827       if (increment_overflow(&y, 1))
01828          return NULL;
01829    }
01830    tmp->tm_year = y;
01831    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01832       return NULL;
01833    tmp->tm_yday = idays;
01834    /*
01835    ** The "extra" mods below avoid overflow problems.
01836    */
01837    tmp->tm_wday = EPOCH_WDAY +
01838       ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01839       (DAYSPERNYEAR % DAYSPERWEEK) +
01840       leaps_thru_end_of(y - 1) -
01841       leaps_thru_end_of(EPOCH_YEAR - 1) +
01842       idays;
01843    tmp->tm_wday %= DAYSPERWEEK;
01844    if (tmp->tm_wday < 0)
01845       tmp->tm_wday += DAYSPERWEEK;
01846    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01847    rem %= SECSPERHOUR;
01848    tmp->tm_min = (int) (rem / SECSPERMIN);
01849    /*
01850    ** A positive leap second requires a special
01851    ** representation. This uses "... ??:59:60" et seq.
01852    */
01853    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01854    ip = mon_lengths[isleap(y)];
01855    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01856       idays -= ip[tmp->tm_mon];
01857    tmp->tm_mday = (int) (idays + 1);
01858    tmp->tm_isdst = 0;
01859 #ifdef TM_GMTOFF
01860    tmp->TM_GMTOFF = offset;
01861 #endif /* defined TM_GMTOFF */
01862    tmp->tm_usec = timep->tv_usec;
01863    return tmp;
01864 }

static int tmcomp ( const struct ast_tm atmp,
const struct ast_tm btmp 
) [static]

Definition at line 1919 of file localtime.c.

References ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.

Referenced by time2sub().

01920 {
01921    int   result;
01922 
01923    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01924       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01925       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01926       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01927       (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
01928       (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
01929          result = atmp->tm_usec - btmp->tm_usec;
01930    return result;
01931 }

static time_t transtime ( const time_t  janfirst,
const int  year,
const struct rule rulep,
const long  offset 
) [static]

Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.

Definition at line 1092 of file localtime.c.

References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, SECSPERDAY, and value.

Referenced by tzparse().

01093 {
01094    int   leapyear;
01095    time_t   value;
01096    int   i;
01097    int      d, m1, yy0, yy1, yy2, dow;
01098 
01099    INITIALIZE(value);
01100    leapyear = isleap(year);
01101    switch (rulep->r_type) {
01102 
01103    case JULIAN_DAY:
01104       /*
01105       ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
01106       ** years.
01107       ** In non-leap years, or if the day number is 59 or less, just
01108       ** add SECSPERDAY times the day number-1 to the time of
01109       ** January 1, midnight, to get the day.
01110       */
01111       value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
01112       if (leapyear && rulep->r_day >= 60)
01113          value += SECSPERDAY;
01114       break;
01115 
01116    case DAY_OF_YEAR:
01117       /*
01118       ** n - day of year.
01119       ** Just add SECSPERDAY times the day number to the time of
01120       ** January 1, midnight, to get the day.
01121       */
01122       value = janfirst + rulep->r_day * SECSPERDAY;
01123       break;
01124 
01125    case MONTH_NTH_DAY_OF_WEEK:
01126       /*
01127       ** Mm.n.d - nth "dth day" of month m.
01128       */
01129       value = janfirst;
01130       for (i = 0; i < rulep->r_mon - 1; ++i)
01131          value += mon_lengths[leapyear][i] * SECSPERDAY;
01132 
01133       /*
01134       ** Use Zeller's Congruence to get day-of-week of first day of
01135       ** month.
01136       */
01137       m1 = (rulep->r_mon + 9) % 12 + 1;
01138       yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
01139       yy1 = yy0 / 100;
01140       yy2 = yy0 % 100;
01141       dow = ((26 * m1 - 2) / 10 +
01142          1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
01143       if (dow < 0)
01144          dow += DAYSPERWEEK;
01145 
01146       /*
01147       ** "dow" is the day-of-week of the first day of the month. Get
01148       ** the day-of-month (zero-origin) of the first "dow" day of the
01149       ** month.
01150       */
01151       d = rulep->r_day - dow;
01152       if (d < 0)
01153          d += DAYSPERWEEK;
01154       for (i = 1; i < rulep->r_week; ++i) {
01155          if (d + DAYSPERWEEK >=
01156             mon_lengths[leapyear][rulep->r_mon - 1])
01157                break;
01158          d += DAYSPERWEEK;
01159       }
01160 
01161       /*
01162       ** "d" is the day-of-month (zero-origin) of the day we want.
01163       */
01164       value += d * SECSPERDAY;
01165       break;
01166    }
01167 
01168    /*
01169    ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
01170    ** question. To get the Epoch-relative time of the specified local
01171    ** time on that day, add the transition time and the current offset
01172    ** from UTC.
01173    */
01174    return value + rulep->r_time + offset;
01175 }

static int tzload ( const char *  name,
struct state *const   sp,
const int  doextend 
) [static]

Definition at line 662 of file localtime.c.

References add_notify(), ast_fully_booted, state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, state::goahead, state::goback, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzparse(), and YEARSPERREPEAT.

Referenced by ast_tzset(), gmtload(), and tzparse().

00663 {
00664    const char *      p;
00665    int         i;
00666    int         fid;
00667    int         stored;
00668    int         nread;
00669    union {
00670       struct tzhead  tzhead;
00671       char     buf[2 * sizeof(struct tzhead) +
00672                2 * sizeof *sp +
00673                4 * TZ_MAX_TIMES];
00674    } u;
00675 
00676    if (name == NULL && (name = TZDEFAULT) == NULL)
00677       return -1;
00678    {
00679       int   doaccess;
00680       /*
00681       ** Section 4.9.1 of the C standard says that
00682       ** "FILENAME_MAX expands to an integral constant expression
00683       ** that is the size needed for an array of char large enough
00684       ** to hold the longest file name string that the implementation
00685       ** guarantees can be opened."
00686       */
00687       char     fullname[FILENAME_MAX + 1];
00688 
00689       if (name[0] == ':')
00690          ++name;
00691       doaccess = name[0] == '/';
00692       if (!doaccess) {
00693          if ((p = TZDIR) == NULL)
00694             return -1;
00695          if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00696             return -1;
00697          (void) strcpy(fullname, p);
00698          (void) strcat(fullname, "/");
00699          (void) strcat(fullname, name);
00700          /*
00701          ** Set doaccess if '.' (as in "../") shows up in name.
00702          */
00703          if (strchr(name, '.') != NULL)
00704             doaccess = TRUE;
00705          name = fullname;
00706       }
00707       if (doaccess && access(name, R_OK) != 0)
00708          return -1;
00709       if ((fid = open(name, OPEN_MODE)) == -1)
00710          return -1;
00711       if (ast_fully_booted) {
00712          /* If we don't wait until Asterisk is fully booted, it's possible
00713           * that the watcher thread gets started in the parent process,
00714           * before daemon(3) is called, and the thread won't propagate to
00715           * the child.  Given that bootup only takes a few seconds, it's
00716           * reasonable to only start the watcher later. */
00717          add_notify(sp, name);
00718       }
00719    }
00720    nread = read(fid, u.buf, sizeof u.buf);
00721    if (close(fid) < 0 || nread <= 0)
00722       return -1;
00723    for (stored = 4; stored <= 8; stored *= 2) {
00724       int      ttisstdcnt;
00725       int      ttisgmtcnt;
00726 
00727       ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00728       ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00729       sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00730       sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00731       sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00732       sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00733       p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00734       if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00735          sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00736          sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00737          sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00738          (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00739          (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00740             return -1;
00741       if (nread - (p - u.buf) <
00742          sp->timecnt * stored +     /* ats */
00743          sp->timecnt +        /* types */
00744          sp->typecnt * 6 +    /* ttinfos */
00745          sp->charcnt +        /* chars */
00746          sp->leapcnt * (stored + 4) +  /* lsinfos */
00747          ttisstdcnt +         /* ttisstds */
00748          ttisgmtcnt)       /* ttisgmts */
00749             return -1;
00750       for (i = 0; i < sp->timecnt; ++i) {
00751          sp->ats[i] = (stored == 4) ?
00752             detzcode(p) : detzcode64(p);
00753          p += stored;
00754       }
00755       for (i = 0; i < sp->timecnt; ++i) {
00756          sp->types[i] = (unsigned char) *p++;
00757          if (sp->types[i] >= sp->typecnt)
00758             return -1;
00759       }
00760       for (i = 0; i < sp->typecnt; ++i) {
00761          struct ttinfo *   ttisp;
00762 
00763          ttisp = &sp->ttis[i];
00764          ttisp->tt_gmtoff = detzcode(p);
00765          p += 4;
00766          ttisp->tt_isdst = (unsigned char) *p++;
00767          if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00768             return -1;
00769          ttisp->tt_abbrind = (unsigned char) *p++;
00770          if (ttisp->tt_abbrind < 0 ||
00771             ttisp->tt_abbrind > sp->charcnt)
00772                return -1;
00773       }
00774       for (i = 0; i < sp->charcnt; ++i)
00775          sp->chars[i] = *p++;
00776       sp->chars[i] = '\0'; /* ensure '\0' at end */
00777       for (i = 0; i < sp->leapcnt; ++i) {
00778          struct lsinfo *   lsisp;
00779 
00780          lsisp = &sp->lsis[i];
00781          lsisp->ls_trans = (stored == 4) ?
00782             detzcode(p) : detzcode64(p);
00783          p += stored;
00784          lsisp->ls_corr = detzcode(p);
00785          p += 4;
00786       }
00787       for (i = 0; i < sp->typecnt; ++i) {
00788          struct ttinfo *   ttisp;
00789 
00790          ttisp = &sp->ttis[i];
00791          if (ttisstdcnt == 0)
00792             ttisp->tt_ttisstd = FALSE;
00793          else {
00794             ttisp->tt_ttisstd = *p++;
00795             if (ttisp->tt_ttisstd != TRUE &&
00796                ttisp->tt_ttisstd != FALSE)
00797                   return -1;
00798          }
00799       }
00800       for (i = 0; i < sp->typecnt; ++i) {
00801          struct ttinfo *   ttisp;
00802 
00803          ttisp = &sp->ttis[i];
00804          if (ttisgmtcnt == 0)
00805             ttisp->tt_ttisgmt = FALSE;
00806          else {
00807             ttisp->tt_ttisgmt = *p++;
00808             if (ttisp->tt_ttisgmt != TRUE &&
00809                ttisp->tt_ttisgmt != FALSE)
00810                   return -1;
00811          }
00812       }
00813       /*
00814       ** Out-of-sort ats should mean we're running on a
00815       ** signed time_t system but using a data file with
00816       ** unsigned values (or vice versa).
00817       */
00818       for (i = 0; i < sp->timecnt - 2; ++i)
00819          if (sp->ats[i] > sp->ats[i + 1]) {
00820             ++i;
00821             if (TYPE_SIGNED(time_t)) {
00822                /*
00823                ** Ignore the end (easy).
00824                */
00825                sp->timecnt = i;
00826             } else {
00827                /*
00828                ** Ignore the beginning (harder).
00829                */
00830                int   j;
00831 
00832                for (j = 0; j + i < sp->timecnt; ++j) {
00833                   sp->ats[j] = sp->ats[j + i];
00834                   sp->types[j] = sp->types[j + i];
00835                }
00836                sp->timecnt = j;
00837             }
00838             break;
00839          }
00840       /*
00841       ** If this is an old file, we're done.
00842       */
00843       if (u.tzhead.tzh_version[0] == '\0')
00844          break;
00845       nread -= p - u.buf;
00846       for (i = 0; i < nread; ++i)
00847          u.buf[i] = p[i];
00848       /*
00849       ** If this is a narrow integer time_t system, we're done.
00850       */
00851       if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00852          break;
00853    }
00854    if (doextend && nread > 2 &&
00855       u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00856       sp->typecnt + 2 <= TZ_MAX_TYPES) {
00857          struct state   ts;
00858          int   result;
00859 
00860          u.buf[nread - 1] = '\0';
00861          result = tzparse(&u.buf[1], &ts, FALSE);
00862          if (result == 0 && ts.typecnt == 2 &&
00863             sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00864                for (i = 0; i < 2; ++i)
00865                   ts.ttis[i].tt_abbrind +=
00866                      sp->charcnt;
00867                for (i = 0; i < ts.charcnt; ++i)
00868                   sp->chars[sp->charcnt++] =
00869                      ts.chars[i];
00870                i = 0;
00871                while (i < ts.timecnt &&
00872                   ts.ats[i] <=
00873                   sp->ats[sp->timecnt - 1])
00874                      ++i;
00875                while (i < ts.timecnt &&
00876                    sp->timecnt < TZ_MAX_TIMES) {
00877                   sp->ats[sp->timecnt] =
00878                      ts.ats[i];
00879                   sp->types[sp->timecnt] =
00880                      sp->typecnt +
00881                      ts.types[i];
00882                   ++sp->timecnt;
00883                   ++i;
00884                }
00885                sp->ttis[sp->typecnt++] = ts.ttis[0];
00886                sp->ttis[sp->typecnt++] = ts.ttis[1];
00887          }
00888    }
00889    i = 2 * YEARSPERREPEAT;
00890    sp->goback = sp->goahead = sp->timecnt > i;
00891    sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
00892       differ_by_repeat(sp->ats[i], sp->ats[0]);
00893    sp->goahead = sp->goahead &&
00894       sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
00895       differ_by_repeat(sp->ats[sp->timecnt - 1],
00896           sp->ats[sp->timecnt - 1 - i]);
00897    return 0;
00898 }

static int tzparse ( const char *  name,
struct state sp,
const int  lastditch 
) [static]
Note:
Given a POSIX section 8-style TZ string, fill in the rule tables as appropriate.

Definition at line 1182 of file localtime.c.

References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, state::timecnt, transtime(), TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, and tzload().

Referenced by ast_tzset(), gmtload(), and tzload().

01183 {
01184    const char *         stdname;
01185    const char *         dstname;
01186    size_t            stdlen;
01187    size_t            dstlen;
01188    long           stdoffset;
01189    long           dstoffset;
01190    time_t *    atp;
01191    unsigned char *   typep;
01192    char *         cp;
01193    int         load_result;
01194 
01195    INITIALIZE(dstname);
01196    stdname = name;
01197    if (lastditch) {
01198       stdlen = strlen(name);  /* length of standard zone name */
01199       name += stdlen;
01200       if (stdlen >= sizeof sp->chars)
01201          stdlen = (sizeof sp->chars) - 1;
01202       stdoffset = 0;
01203    } else {
01204       if (*name == '<') {
01205          name++;
01206          stdname = name;
01207          name = getqzname(name, '>');
01208          if (*name != '>')
01209             return -1;
01210          stdlen = name - stdname;
01211          name++;
01212       } else {
01213          name = getzname(name);
01214          stdlen = name - stdname;
01215       }
01216       if (*name == '\0')
01217          return -1;
01218       name = getoffset(name, &stdoffset);
01219       if (name == NULL)
01220          return -1;
01221    }
01222    load_result = tzload(TZDEFRULES, sp, FALSE);
01223    if (load_result != 0)
01224       sp->leapcnt = 0;     /* so, we're off a little */
01225    if (*name != '\0') {
01226       if (*name == '<') {
01227          dstname = ++name;
01228          name = getqzname(name, '>');
01229          if (*name != '>')
01230             return -1;
01231          dstlen = name - dstname;
01232          name++;
01233       } else {
01234          dstname = name;
01235          name = getzname(name);
01236          dstlen = name - dstname; /* length of DST zone name */
01237       }
01238       if (*name != '\0' && *name != ',' && *name != ';') {
01239          name = getoffset(name, &dstoffset);
01240          if (name == NULL)
01241             return -1;
01242       } else   dstoffset = stdoffset - SECSPERHOUR;
01243       if (*name == '\0' && load_result != 0)
01244          name = TZDEFRULESTRING;
01245       if (*name == ',' || *name == ';') {
01246          struct rule start;
01247          struct rule end;
01248          int   year;
01249          time_t   janfirst;
01250          time_t      starttime;
01251          time_t      endtime;
01252 
01253          ++name;
01254          if ((name = getrule(name, &start)) == NULL)
01255             return -1;
01256          if (*name++ != ',')
01257             return -1;
01258          if ((name = getrule(name, &end)) == NULL)
01259             return -1;
01260          if (*name != '\0')
01261             return -1;
01262          sp->typecnt = 2;  /* standard time and DST */
01263          /*
01264          ** Two transitions per year, from EPOCH_YEAR forward.
01265          */
01266          sp->ttis[0].tt_gmtoff = -dstoffset;
01267          sp->ttis[0].tt_isdst = 1;
01268          sp->ttis[0].tt_abbrind = stdlen + 1;
01269          sp->ttis[1].tt_gmtoff = -stdoffset;
01270          sp->ttis[1].tt_isdst = 0;
01271          sp->ttis[1].tt_abbrind = 0;
01272          atp = sp->ats;
01273          typep = sp->types;
01274          janfirst = 0;
01275          sp->timecnt = 0;
01276          for (year = EPOCH_YEAR;
01277              sp->timecnt + 2 <= TZ_MAX_TIMES;
01278              ++year) {
01279                time_t   newfirst;
01280 
01281             starttime = transtime(janfirst, year, &start,
01282                stdoffset);
01283             endtime = transtime(janfirst, year, &end,
01284                dstoffset);
01285             if (starttime > endtime) {
01286                *atp++ = endtime;
01287                *typep++ = 1;  /* DST ends */
01288                *atp++ = starttime;
01289                *typep++ = 0;  /* DST begins */
01290             } else {
01291                *atp++ = starttime;
01292                *typep++ = 0;  /* DST begins */
01293                *atp++ = endtime;
01294                *typep++ = 1;  /* DST ends */
01295             }
01296             sp->timecnt += 2;
01297             newfirst = janfirst;
01298             newfirst += year_lengths[isleap(year)] *
01299                SECSPERDAY;
01300             if (newfirst <= janfirst)
01301                break;
01302             janfirst = newfirst;
01303          }
01304       } else {
01305          long  theirstdoffset;
01306          long  theirdstoffset;
01307          long  theiroffset;
01308          int   isdst;
01309          int   i;
01310          int   j;
01311 
01312          if (*name != '\0')
01313             return -1;
01314          /*
01315          ** Initial values of theirstdoffset and theirdstoffset.
01316          */
01317          theirstdoffset = 0;
01318          for (i = 0; i < sp->timecnt; ++i) {
01319             j = sp->types[i];
01320             if (!sp->ttis[j].tt_isdst) {
01321                theirstdoffset =
01322                   -sp->ttis[j].tt_gmtoff;
01323                break;
01324             }
01325          }
01326          theirdstoffset = 0;
01327          for (i = 0; i < sp->timecnt; ++i) {
01328             j = sp->types[i];
01329             if (sp->ttis[j].tt_isdst) {
01330                theirdstoffset =
01331                   -sp->ttis[j].tt_gmtoff;
01332                break;
01333             }
01334          }
01335          /*
01336          ** Initially we're assumed to be in standard time.
01337          */
01338          isdst = FALSE;
01339          theiroffset = theirstdoffset;
01340          /*
01341          ** Now juggle transition times and types
01342          ** tracking offsets as you do.
01343          */
01344          for (i = 0; i < sp->timecnt; ++i) {
01345             j = sp->types[i];
01346             sp->types[i] = sp->ttis[j].tt_isdst;
01347             if (sp->ttis[j].tt_ttisgmt) {
01348                /* No adjustment to transition time */
01349             } else {
01350                /*
01351                ** If summer time is in effect, and the
01352                ** transition time was not specified as
01353                ** standard time, add the summer time
01354                ** offset to the transition time;
01355                ** otherwise, add the standard time
01356                ** offset to the transition time.
01357                */
01358                /*
01359                ** Transitions from DST to DDST
01360                ** will effectively disappear since
01361                ** POSIX provides for only one DST
01362                ** offset.
01363                */
01364                if (isdst && !sp->ttis[j].tt_ttisstd) {
01365                   sp->ats[i] += dstoffset -
01366                      theirdstoffset;
01367                } else {
01368                   sp->ats[i] += stdoffset -
01369                      theirstdoffset;
01370                }
01371             }
01372             theiroffset = -sp->ttis[j].tt_gmtoff;
01373             if (sp->ttis[j].tt_isdst)
01374                theirdstoffset = theiroffset;
01375             else  theirstdoffset = theiroffset;
01376          }
01377          /*
01378          ** Finally, fill in ttis.
01379          ** ttisstd and ttisgmt need not be handled.
01380          */
01381          sp->ttis[0].tt_gmtoff = -stdoffset;
01382          sp->ttis[0].tt_isdst = FALSE;
01383          sp->ttis[0].tt_abbrind = 0;
01384          sp->ttis[1].tt_gmtoff = -dstoffset;
01385          sp->ttis[1].tt_isdst = TRUE;
01386          sp->ttis[1].tt_abbrind = stdlen + 1;
01387          sp->typecnt = 2;
01388       }
01389    } else {
01390       dstlen = 0;
01391       sp->typecnt = 1;     /* only standard time */
01392       sp->timecnt = 0;
01393       sp->ttis[0].tt_gmtoff = -stdoffset;
01394       sp->ttis[0].tt_isdst = 0;
01395       sp->ttis[0].tt_abbrind = 0;
01396    }
01397    sp->charcnt = stdlen + 1;
01398    if (dstlen != 0)
01399       sp->charcnt += dstlen + 1;
01400    if ((size_t) sp->charcnt > sizeof sp->chars)
01401       return -1;
01402    cp = sp->chars;
01403    (void) strncpy(cp, stdname, stdlen);
01404    cp += stdlen;
01405    *cp++ = '\0';
01406    if (dstlen != 0) {
01407       (void) strncpy(cp, dstname, dstlen);
01408       *(cp + dstlen) = '\0';
01409    }
01410    return 0;
01411 }


Variable Documentation

char elsieid[] = "@(#)localtime.c 8.5" [static]

Definition at line 84 of file localtime.c.

const char gmt[] = "GMT" [static]

Definition at line 112 of file localtime.c.

Definition at line 267 of file localtime.c.

Definition at line 268 of file localtime.c.

int inotify_fd = -1 [static]

Definition at line 270 of file localtime.c.

Referenced by scan_thread().

pthread_t inotify_thread = AST_PTHREADT_NULL [static]

Definition at line 266 of file localtime.c.

const int mon_lengths[2][MONSPERYEAR] [static]
Initial value:
 {
   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}

Definition at line 900 of file localtime.c.

struct timeval WRONG = { 0, 0 } [static]

Definition at line 113 of file localtime.c.

const int year_lengths[2] [static]
Initial value:

Definition at line 905 of file localtime.c.


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1