CLeanup PBX patch and add localtime stuff for saytime (bug #168)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1506 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
c511b967ed
commit
56f915e783
20
Makefile
20
Makefile
|
@ -153,12 +153,7 @@ _all: all
|
|||
all: depend asterisk subdirs
|
||||
|
||||
editline/config.h:
|
||||
@if [ -d editline ]; then \
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
else \
|
||||
echo "You need to do a cvs update -d not just cvs update"; \
|
||||
exit 1; \
|
||||
fi
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
|
||||
editline/libedit.a: editline/config.h
|
||||
$(MAKE) -C editline libedit.a
|
||||
|
@ -199,8 +194,16 @@ build.h:
|
|||
./make_build_h
|
||||
endif
|
||||
|
||||
asterisk: editline/libedit.a db1-ast/libdb1.a $(OBJS)
|
||||
$(CC) $(DEBUG) -o asterisk -rdynamic $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a
|
||||
stdtime/localtime.o:
|
||||
@if [ -d stdtime ]; then \
|
||||
$(MAKE) -C stdtime; \
|
||||
else \
|
||||
echo "You need to do a cvs update -d not just cvs update"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/localtime.o $(OBJS)
|
||||
$(CC) $(DEBUG) -o asterisk -rdynamic $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a stdtime/localtime.o
|
||||
|
||||
subdirs:
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x || exit 1 ; done
|
||||
|
@ -212,6 +215,7 @@ clean:
|
|||
rm -f ast_expr.c
|
||||
@if [ -e editline/Makefile ]; then $(MAKE) -C editline clean ; fi
|
||||
$(MAKE) -C db1-ast clean
|
||||
$(MAKE) -C stdtime clean
|
||||
|
||||
datafiles: all
|
||||
mkdir -p $(ASTVARLIBDIR)/sounds/digits
|
||||
|
|
|
@ -106,26 +106,26 @@ static char *synopsis_vm =
|
|||
"Leave a voicemail message";
|
||||
|
||||
static char *descrip_vm =
|
||||
" VoiceMail([s|u|b]extension[@context]): Leaves voicemail for a given extension (must\n"
|
||||
"be configured in voicemail.conf). If the extension is preceeded by an 's'"
|
||||
"then instructions for leaving the message will be skipped. If the extension\n"
|
||||
"is preceeded by 'u' then the \"unavailable\" message will be played (that is, \n"
|
||||
"/var/lib/asterisk/sounds/vm/<exten>/unavail) if it exists. If the extension\n"
|
||||
"is preceeded by a 'b' then the the busy message will be played (that is,\n"
|
||||
"busy instead of unavail). \n"
|
||||
"Returns -1 on error or mailbox not found, or if the user hangs up. \n"
|
||||
"Otherwise, it returns 0. \n";
|
||||
" VoiceMail([s|u|b]extension[@context]): Leaves voicemail for a given\n"
|
||||
"extension (must be configured in voicemail.conf). If the extension is\n"
|
||||
"preceded by an 's' then instructions for leaving the message will be\n"
|
||||
"skipped. If the extension is preceeded by 'u' then the \"unavailable\"\n"
|
||||
"message will be played (/var/lib/asterisk/sounds/vm/<exten>/unavail) if it\n"
|
||||
"exists. If the extension is preceeded by a 'b' then the the busy message\n"
|
||||
"will be played (that is, busy instead of unavail).\n"
|
||||
"Returns -1 on error or mailbox not found, or if the user hangs up.\n"
|
||||
"Otherwise, it returns 0.\n";
|
||||
|
||||
static char *synopsis_vmain =
|
||||
"Enter voicemail system";
|
||||
|
||||
static char *descrip_vmain =
|
||||
" VoiceMailMain([[s]mailbox][@context]): Enters the main voicemail system for the checking of\n"
|
||||
"voicemail. The mailbox can be passed as the option, which will stop the\n"
|
||||
"voicemail system from prompting the user for the mailbox. If the mailbox\n"
|
||||
"is preceded by 's' then the password check will be skipped. If a context is\n"
|
||||
"specified, logins are considered in that context only. Returns -1 if\n"
|
||||
"the user hangs up or 0 otherwise.\n";
|
||||
" VoiceMailMain([[s]mailbox][@context]): Enters the main voicemail system\n"
|
||||
"for the checking of voicemail. The mailbox can be passed as the option,\n"
|
||||
"which will stop the voicemail system from prompting the user for the mailbox.\n"
|
||||
"If the mailbox is preceded by 's' then the password check will be skipped. If\n"
|
||||
"a context is specified, logins are considered in that context only.\n"
|
||||
"Returns -1 if the user hangs up or 0 otherwise.\n";
|
||||
|
||||
/* Leave a message */
|
||||
static char *app = "VoiceMail2";
|
||||
|
@ -1897,298 +1897,13 @@ static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int play_datetime_format(struct ast_channel *chan, time_t time, struct vm_state *vms, struct vm_zone *zone)
|
||||
{
|
||||
int d = 0, offset = 0, sndoffset = 0;
|
||||
char sndfile[256], nextmsg[256];
|
||||
struct tm tm;
|
||||
char *tzenv, current_tz[256] = "", *qmark;
|
||||
|
||||
tzenv = getenv("TZ");
|
||||
if (tzenv != NULL)
|
||||
strncpy(current_tz, tzenv, sizeof(current_tz) - 1);
|
||||
if (zone->timezone && strcmp(current_tz,zone->timezone)) {
|
||||
setenv("TZ", zone->timezone, 1);
|
||||
tzset();
|
||||
localtime_r(&time, &tm);
|
||||
if (tzenv != NULL)
|
||||
setenv("TZ", current_tz, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
} else {
|
||||
/* No need to change the timezone */
|
||||
localtime_r(&time, &tm);
|
||||
}
|
||||
|
||||
/* Check for a subexpression */
|
||||
if ((qmark = index(zone->msg_format, '?'))) {
|
||||
/* TODO Allow subexpressions - we probably need to implement a parser here. */
|
||||
}
|
||||
|
||||
for (offset=0 ; zone->msg_format[offset] != '\0' ; offset++) {
|
||||
ast_log(LOG_NOTICE, "Parsing %c in %s\n", zone->msg_format[offset], zone->msg_format);
|
||||
switch (zone->msg_format[offset]) {
|
||||
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
|
||||
case '\'':
|
||||
/* Literal name of a sound file */
|
||||
sndoffset=0;
|
||||
for (sndoffset=0 ; zone->msg_format[++offset] != '\'' ; sndoffset++)
|
||||
sndfile[sndoffset] = zone->msg_format[offset];
|
||||
sndfile[sndoffset] = '\0';
|
||||
snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/%s", sndfile);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
break;
|
||||
case '$':
|
||||
/* Ooooh, variables and/or expressions */
|
||||
{
|
||||
struct vm_zone z;
|
||||
memcpy(&z,zone,sizeof(struct vm_zone));
|
||||
pbx_substitute_variables_helper(chan, zone->msg_format + offset, z.msg_format, sizeof(z.msg_format));
|
||||
d = play_datetime_format(chan, time, vms, &z);
|
||||
/* Subtract one, so that when the for loop increments, we point at the nil */
|
||||
offset = strlen(zone->msg_format) - 1;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
/* Sunday - Saturday */
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "day-%d", tm.tm_wday);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
break;
|
||||
case 'B':
|
||||
case 'b':
|
||||
case 'h':
|
||||
/* January - December */
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "mon-%d", tm.tm_mon);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
break;
|
||||
case 'd':
|
||||
case 'e':
|
||||
/* First - Thirtyfirst */
|
||||
if ((tm.tm_mday < 21) || (tm.tm_mday == 30)) {
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "h-%d", tm.tm_mday);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
} else if (tm.tm_mday == 31) {
|
||||
/* "Thirty" and "first" */
|
||||
d = wait_file(chan,vms,DIGITS_DIR "30");
|
||||
if (!d) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "h-1");
|
||||
}
|
||||
} else {
|
||||
/* Between 21 and 29 - two sounds */
|
||||
d = wait_file(chan,vms,DIGITS_DIR "20");
|
||||
if (!d) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "h-%d", tm.tm_mday - 20);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
/* Year */
|
||||
if (tm.tm_year > 99) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "2");
|
||||
if (!d) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "thousand");
|
||||
}
|
||||
if (tm.tm_year > 100) {
|
||||
if (!d) {
|
||||
/* This works until the end of 2020 */
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year - 100);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tm.tm_year < 1) {
|
||||
/* I'm not going to handle 1900 and prior */
|
||||
/* We'll just be silent on the year, instead of bombing out. */
|
||||
} else {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "19");
|
||||
if (!d) {
|
||||
if (tm.tm_year < 20) {
|
||||
/* 1901 - 1920 */
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
} else {
|
||||
/* 1921 - 1999 */
|
||||
int ten, one;
|
||||
ten = tm.tm_year / 10;
|
||||
one = tm.tm_year % 10;
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten * 10);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
if (!d) {
|
||||
if (one != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
case 'l':
|
||||
/* 12-Hour */
|
||||
if (tm.tm_hour == 0)
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "12");
|
||||
else if (tm.tm_hour > 12)
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour - 12);
|
||||
else
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
break;
|
||||
case 'H':
|
||||
case 'k':
|
||||
/* 24-Hour */
|
||||
if (zone->msg_format[offset] == 'H') {
|
||||
/* e.g. oh-eight */
|
||||
if (tm.tm_hour < 10) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "oh");
|
||||
}
|
||||
} else {
|
||||
/* e.g. eight */
|
||||
if (tm.tm_hour == 0) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "oh");
|
||||
}
|
||||
}
|
||||
if (!d) {
|
||||
if (tm.tm_hour != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/digits/%d", tm.tm_hour);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
/* Minute */
|
||||
if (tm.tm_min == 0) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "oclock");
|
||||
} else if (tm.tm_min < 10) {
|
||||
d = wait_file(chan,vms,DIGITS_DIR "oh");
|
||||
if (!d) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
} else if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
} else {
|
||||
int ten, one;
|
||||
ten = (tm.tm_min / 10) * 10;
|
||||
one = (tm.tm_min % 10);
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
if (!d) {
|
||||
/* Fifty, not fifty-zero */
|
||||
if (one != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
/* AM/PM */
|
||||
if ((tm.tm_hour == 0) || (tm.tm_hour > 11))
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "p-m");
|
||||
else
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "a-m");
|
||||
d = wait_file(chan,vms,nextmsg);
|
||||
break;
|
||||
case 'Q':
|
||||
/* Shorthand for "Today", "Yesterday", or ABdY */
|
||||
{
|
||||
struct timeval now;
|
||||
struct tm tmnow;
|
||||
time_t beg_today, tnow;
|
||||
|
||||
gettimeofday(&now,NULL);
|
||||
tnow = now.tv_sec;
|
||||
localtime_r(&tnow,&tmnow);
|
||||
tmnow.tm_hour = 0;
|
||||
tmnow.tm_min = 0;
|
||||
tmnow.tm_sec = 0;
|
||||
beg_today = mktime(&tmnow);
|
||||
if (beg_today < time) {
|
||||
/* Today */
|
||||
d = wait_file(chan,vms,DIGITS_DIR "today");
|
||||
} else if (beg_today - 86400 < time) {
|
||||
/* Yesterday */
|
||||
d = wait_file(chan,vms,DIGITS_DIR "yesterday");
|
||||
} else {
|
||||
struct vm_zone z;
|
||||
memcpy(&z, zone, sizeof(struct vm_zone));
|
||||
strcpy(z.msg_format, "ABdY");
|
||||
d = play_datetime_format(chan, time, vms, &z);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
/* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
|
||||
{
|
||||
struct timeval now;
|
||||
struct tm tmnow;
|
||||
time_t beg_today, tnow;
|
||||
|
||||
gettimeofday(&now,NULL);
|
||||
tnow = now.tv_sec;
|
||||
localtime_r(&tnow,&tmnow);
|
||||
tmnow.tm_hour = 0;
|
||||
tmnow.tm_min = 0;
|
||||
tmnow.tm_sec = 0;
|
||||
beg_today = mktime(&tmnow);
|
||||
if (beg_today < time) {
|
||||
/* Today */
|
||||
} else if (beg_today - 86400 < time) {
|
||||
/* Yesterday */
|
||||
d = wait_file(chan,vms,DIGITS_DIR "yesterday");
|
||||
} else if (beg_today - 86400 * 6 < time) {
|
||||
/* Within the last week */
|
||||
struct vm_zone z;
|
||||
memcpy(&z, zone, sizeof(struct vm_zone));
|
||||
strcpy(z.msg_format, "A");
|
||||
d = play_datetime_format(chan, time, vms, &z);
|
||||
} else {
|
||||
struct vm_zone z;
|
||||
memcpy(&z, zone, sizeof(struct vm_zone));
|
||||
strcpy(z.msg_format, "ABdY");
|
||||
d = play_datetime_format(chan, time, vms, &z);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
{
|
||||
struct vm_zone z;
|
||||
memcpy(&z, zone, sizeof(struct vm_zone));
|
||||
strcpy(z.msg_format, "HM");
|
||||
d = play_datetime_format(chan, time, vms, &z);
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
case ' ':
|
||||
/* Just ignore spaces and tabs */
|
||||
break;
|
||||
default:
|
||||
/* Unknown character */
|
||||
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c\n", zone->msg_format, zone->msg_format[offset]);
|
||||
}
|
||||
/* Jump out on DTMF */
|
||||
if (d) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
|
||||
{
|
||||
int res = 0;
|
||||
char filename[256], *origtime, temp[256];
|
||||
char filename[256], *origtime;
|
||||
struct vm_zone *the_zone = NULL;
|
||||
struct ast_config *msg_cfg;
|
||||
time_t t, tnow;
|
||||
struct timeval tv_now;
|
||||
struct tm time_now, time_then;
|
||||
time_t t;
|
||||
long tin;
|
||||
|
||||
make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
|
||||
|
@ -2229,6 +1944,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v
|
|||
strncpy(the_zone->msg_format, "'vm-received' q 'digits/at' IMp", sizeof(the_zone->msg_format) - 1);
|
||||
}
|
||||
|
||||
/* No internal variable parsing for now, so we'll comment it out for the time being */
|
||||
#if 0
|
||||
/* Set the DIFF_* variables */
|
||||
localtime_r(&t, &time_now);
|
||||
gettimeofday(&tv_now,NULL);
|
||||
|
@ -2243,9 +1960,11 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v
|
|||
pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
|
||||
|
||||
/* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
|
||||
|
||||
res = play_datetime_format(chan, t, vms, the_zone);
|
||||
#endif
|
||||
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
|
||||
#if 0
|
||||
pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Custom localtime functions for multiple timezones
|
||||
*
|
||||
* Copyright (C) 2003, Mark Spencer
|
||||
*
|
||||
* Tilghman Lesher <tlesher@vcch.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_LOCALTIME_H
|
||||
#define _ASTERISK_LOCALTIME_H
|
||||
|
||||
extern int ast_tzsetwall(void);
|
||||
extern void ast_tzset(const char *name);
|
||||
extern struct tm *ast_localtime(const time_t *timep, struct tm *p_tm, const char *zone);
|
||||
extern time_t ast_mktime(struct tm * const tmp, const char *zone);
|
||||
|
||||
#endif
|
|
@ -523,6 +523,8 @@ extern void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char
|
|||
extern void pbx_builtin_clear_globals(void);
|
||||
extern void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
|
||||
|
||||
int ast_extension_patmatch(const char *pattern, const char *data);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -69,6 +69,8 @@ int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang);
|
|||
|
||||
int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang);
|
||||
|
||||
int ast_say_date_with_format(struct ast_channel *chan, time_t t, char *ints, char *lang, char *format, char *timezone);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
18
pbx.c
18
pbx.c
|
@ -144,8 +144,6 @@ struct ast_hint {
|
|||
struct ast_hint *next;
|
||||
};
|
||||
|
||||
int ast_extension_patmatch(const char *pattern, const char *data);
|
||||
|
||||
static int pbx_builtin_prefix(struct ast_channel *, void *);
|
||||
static int pbx_builtin_suffix(struct ast_channel *, void *);
|
||||
static int pbx_builtin_stripmsd(struct ast_channel *, void *);
|
||||
|
@ -172,6 +170,7 @@ static int pbx_builtin_saynumber(struct ast_channel *, void *);
|
|||
static int pbx_builtin_saydigits(struct ast_channel *, void *);
|
||||
void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
|
||||
char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name);
|
||||
static int ast_extension_patmatch_repeated(const char *pattern, const char *data, const int num);
|
||||
|
||||
static struct varshead globals = AST_LIST_HEAD_INITIALIZER(varshead);
|
||||
|
||||
|
@ -522,14 +521,13 @@ char patmatch_group[80] = "";
|
|||
variables, starting with $1, $2 and so on.
|
||||
* alternation as in (01|0|99) ("01 or 0 or 99")
|
||||
*/
|
||||
int ast_extension_patmatch(const char *pattern, char *data)
|
||||
int ast_extension_patmatch(const char *pattern, const char *data)
|
||||
{
|
||||
int i,border=0;
|
||||
char *where;
|
||||
static char prev = '\0';
|
||||
static char groupdata[80] = "";
|
||||
static char *group = patmatch_group;
|
||||
int groupcounter = patmatch_groupcounter;
|
||||
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, " >>> \"%s\" =~ /%s/\n", data, pattern);
|
||||
|
@ -571,7 +569,7 @@ int ast_extension_patmatch(const char *pattern, char *data)
|
|||
|
||||
case '{': /* quantifier {n[,m]} */
|
||||
{
|
||||
char *comma;
|
||||
char *comma=NULL;
|
||||
int cpos;
|
||||
where=strchr(pattern,'}');
|
||||
if (where) {
|
||||
|
@ -636,11 +634,10 @@ int ast_extension_patmatch(const char *pattern, char *data)
|
|||
}
|
||||
prev = *tmp;
|
||||
if (i >= from || !from) { /* if found */
|
||||
int l = strlen(groupdata) - strlen(data);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, " >>>> found '%s' in data '%s' after %d runs\n", group, data, i);
|
||||
char name[16];
|
||||
data = data + (i * (strlen(group)- 1)) - 1;
|
||||
int l = strlen(groupdata) - strlen(data);
|
||||
/* data = data-i+from-1; */ /* possible failure here! */
|
||||
if (prev == ')') { /* grouping => capture */
|
||||
*(group+strlen(group)-1) = '\0';
|
||||
|
@ -708,7 +705,7 @@ int ast_extension_patmatch(const char *pattern, char *data)
|
|||
s = scopy = (char *) malloc(strlen(pattern));
|
||||
sepcopy = (char *) malloc(strlen(pattern));
|
||||
strcpy(s,group);
|
||||
while (sep = strsep(&s,"|")) {
|
||||
while ((sep = strsep(&s,"|"))) {
|
||||
strcpy(sepcopy,sep);
|
||||
strcat(sepcopy,pattern+border+1);
|
||||
if (option_debug)
|
||||
|
@ -737,7 +734,6 @@ int ast_extension_patmatch(const char *pattern, char *data)
|
|||
return 0;
|
||||
} else {
|
||||
if (pattern[1] != '{') { /* capture without quantifiers */
|
||||
char name[16];
|
||||
int l = strlen(groupdata) - strlen(data);
|
||||
groupdata[l-1] = '\0';
|
||||
*(group+strlen(group)-1) = '\0';
|
||||
|
@ -810,7 +806,7 @@ int ast_extension_patmatch(const char *pattern, char *data)
|
|||
}
|
||||
|
||||
/* try exactly num repetitions, from high to from */
|
||||
int ast_extension_patmatch_repeated(const char *pattern, char *data, const int num)
|
||||
static int ast_extension_patmatch_repeated(const char *pattern, const char *data, const int num)
|
||||
{
|
||||
int i;
|
||||
ast_log(LOG_DEBUG, " >>> try %d repetitions of '%s' in data '%s'\n", num, pattern, data);
|
||||
|
@ -848,7 +844,7 @@ int ast_extension_match(char *pattern, char *data)
|
|||
|
||||
static int extension_close(char *pattern, char *data, int needmore)
|
||||
{
|
||||
int match;
|
||||
int match=1;
|
||||
/* If "data" is longer, it can'be a subset of pattern unless
|
||||
pattern is a pattern match */
|
||||
if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
|
||||
|
|
286
say.c
286
say.c
|
@ -12,12 +12,21 @@
|
|||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/localtime.h>
|
||||
#include "asterisk.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIGITS_DIR AST_SOUNDS "/digits/"
|
||||
|
||||
int ast_say_digit_str(struct ast_channel *chan, char *fn2, char *ints, char *lang)
|
||||
{
|
||||
/* XXX Merge with full version? XXX */
|
||||
|
@ -105,14 +114,14 @@ int ast_say_number_full(struct ast_channel *chan, int num, char *ints, char *lan
|
|||
playh++;
|
||||
num -= ((num / 100) * 100);
|
||||
} else {
|
||||
if (num < 1000000) {
|
||||
if (num < 1000000) { /* 1,000,000 */
|
||||
res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd);
|
||||
if (res)
|
||||
return res;
|
||||
num = num % 1000;
|
||||
snprintf(fn, sizeof(fn), "digits/thousand");
|
||||
} else {
|
||||
if (num < 1000000000) {
|
||||
if (num < 1000000000) { /* 1,000,000,000 */
|
||||
res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd);
|
||||
if (res)
|
||||
return res;
|
||||
|
@ -204,11 +213,7 @@ int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
|
|||
struct tm tm;
|
||||
char fn[256];
|
||||
int res = 0;
|
||||
localtime_r(&t,&tm);
|
||||
if (!&tm) {
|
||||
ast_log(LOG_WARNING, "Unable to derive local time\n");
|
||||
return -1;
|
||||
}
|
||||
ast_localtime(&t,&tm,NULL);
|
||||
if (!res) {
|
||||
snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
|
||||
res = ast_streamfile(chan, fn, lang);
|
||||
|
@ -231,16 +236,267 @@ int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int wait_file(struct ast_channel *chan, char *ints, char *file, char *lang)
|
||||
{
|
||||
int res;
|
||||
if ((res = ast_streamfile(chan, file, lang)))
|
||||
ast_log(LOG_WARNING, "Unable to play message %s\n", file);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, ints);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone)
|
||||
{
|
||||
struct tm tm;
|
||||
int res=0, offset, sndoffset;
|
||||
char sndfile[256], nextmsg[256];
|
||||
|
||||
ast_log(LOG_DEBUG, "ast_say_date_with_format() called\n");
|
||||
|
||||
ast_localtime(&time,&tm,timezone);
|
||||
|
||||
ast_log(LOG_DEBUG, "ast_localtime() returned\n");
|
||||
|
||||
for (offset=0 ; format[offset] != '\0' ; offset++) {
|
||||
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
|
||||
switch (format[offset]) {
|
||||
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
|
||||
case '\'':
|
||||
/* Literal name of a sound file */
|
||||
sndoffset=0;
|
||||
for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
|
||||
sndfile[sndoffset] = format[offset];
|
||||
sndfile[sndoffset] = '\0';
|
||||
snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/%s", sndfile);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
/* Sunday - Saturday */
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "day-%d", tm.tm_wday);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
break;
|
||||
case 'B':
|
||||
case 'b':
|
||||
case 'h':
|
||||
/* January - December */
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "mon-%d", tm.tm_mon);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
break;
|
||||
case 'd':
|
||||
case 'e':
|
||||
/* First - Thirtyfirst */
|
||||
if ((tm.tm_mday < 21) || (tm.tm_mday == 30)) {
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "h-%d", tm.tm_mday);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
} else if (tm.tm_mday == 31) {
|
||||
/* "Thirty" and "first" */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "30",lang);
|
||||
if (!res) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "h-1",lang);
|
||||
}
|
||||
} else {
|
||||
/* Between 21 and 29 - two sounds */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "20",lang);
|
||||
if (!res) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "h-%d", tm.tm_mday - 20);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
/* Year */
|
||||
if (tm.tm_year > 99) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "2",lang);
|
||||
if (!res) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "thousand",lang);
|
||||
}
|
||||
if (tm.tm_year > 100) {
|
||||
if (!res) {
|
||||
/* This works until the end of 2020 */
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year - 100);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tm.tm_year < 1) {
|
||||
/* I'm not going to handle 1900 and prior */
|
||||
/* We'll just be silent on the year, instead of bombing out. */
|
||||
} else {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "19",lang);
|
||||
if (!res) {
|
||||
if (tm.tm_year <= 9) {
|
||||
/* 1901 - 1909 */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
|
||||
if (!res) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
} else if (tm.tm_year <= 20) {
|
||||
/* 1910 - 1920 */
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
} else {
|
||||
/* 1921 - 1999 */
|
||||
int ten, one;
|
||||
ten = tm.tm_year / 10;
|
||||
one = tm.tm_year % 10;
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten * 10);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
if (!res) {
|
||||
if (one != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
case 'l':
|
||||
/* 12-Hour */
|
||||
if (tm.tm_hour == 0)
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "12");
|
||||
else if (tm.tm_hour > 12)
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour - 12);
|
||||
else
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
break;
|
||||
case 'H':
|
||||
case 'k':
|
||||
/* 24-Hour */
|
||||
if (format[offset] == 'H') {
|
||||
/* e.g. oh-eight */
|
||||
if (tm.tm_hour < 10) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
|
||||
}
|
||||
} else {
|
||||
/* e.g. eight */
|
||||
if (tm.tm_hour == 0) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
if (tm.tm_hour != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/digits/%d", tm.tm_hour);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
/* Minute */
|
||||
if (tm.tm_min == 0) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "oclock",lang);
|
||||
} else if (tm.tm_min < 10) {
|
||||
res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
|
||||
if (!res) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
} else if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
} else {
|
||||
int ten, one;
|
||||
ten = (tm.tm_min / 10) * 10;
|
||||
one = (tm.tm_min % 10);
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
if (!res) {
|
||||
/* Fifty, not fifty-zero */
|
||||
if (one != 0) {
|
||||
snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
/* AM/PM */
|
||||
if ((tm.tm_hour == 0) || (tm.tm_hour > 11))
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "p-m");
|
||||
else
|
||||
snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "a-m");
|
||||
res = wait_file(chan,ints,nextmsg,lang);
|
||||
break;
|
||||
case 'Q':
|
||||
/* Shorthand for "Today", "Yesterday", or ABdY */
|
||||
{
|
||||
struct timeval now;
|
||||
struct tm tmnow;
|
||||
time_t beg_today;
|
||||
|
||||
gettimeofday(&now,NULL);
|
||||
ast_localtime(&now.tv_sec,&tmnow,timezone);
|
||||
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
|
||||
/* In any case, it saves not having to do ast_mktime() */
|
||||
beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
|
||||
if (beg_today < time) {
|
||||
/* Today */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "today",lang);
|
||||
} else if (beg_today - 86400 < time) {
|
||||
/* Yesterday */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
|
||||
} else {
|
||||
res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
/* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
|
||||
{
|
||||
struct timeval now;
|
||||
struct tm tmnow;
|
||||
time_t beg_today;
|
||||
|
||||
gettimeofday(&now,NULL);
|
||||
ast_localtime(&now.tv_sec,&tmnow,timezone);
|
||||
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
|
||||
/* In any case, it saves not having to do ast_mktime() */
|
||||
beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
|
||||
if (beg_today < time) {
|
||||
/* Today */
|
||||
} else if ((beg_today - 86400) < time) {
|
||||
/* Yesterday */
|
||||
res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
|
||||
} else if (beg_today - 86400 * 6 < time) {
|
||||
/* Within the last week */
|
||||
res = ast_say_date_with_format(chan, time, ints, lang, "A", timezone);
|
||||
} else {
|
||||
res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone);
|
||||
break;
|
||||
case ' ':
|
||||
case ' ':
|
||||
/* Just ignore spaces and tabs */
|
||||
break;
|
||||
default:
|
||||
/* Unknown character */
|
||||
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
|
||||
}
|
||||
/* Jump out on DTMF */
|
||||
if (res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang)
|
||||
{
|
||||
struct tm tm;
|
||||
int res = 0;
|
||||
int hour, pm=0;
|
||||
localtime_r(&t,&tm);
|
||||
if (!&tm) {
|
||||
ast_log(LOG_WARNING, "Unable to derive local time\n");
|
||||
return -1;
|
||||
}
|
||||
hour = tm.tm_hour;
|
||||
if (!hour)
|
||||
hour = 12;
|
||||
|
@ -288,10 +544,6 @@ int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang)
|
|||
int res = 0;
|
||||
int hour, pm=0;
|
||||
localtime_r(&t,&tm);
|
||||
if (!&tm) {
|
||||
ast_log(LOG_WARNING, "Unable to derive local time\n");
|
||||
return -1;
|
||||
}
|
||||
if (!res) {
|
||||
snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
|
||||
res = ast_streamfile(chan, fn, lang);
|
||||
|
@ -361,10 +613,6 @@ int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, ch
|
|||
time(&nowt);
|
||||
|
||||
localtime_r(&t,&tm);
|
||||
if (!&tm) {
|
||||
ast_log(LOG_WARNING, "Unable to derive local time\n");
|
||||
return -1;
|
||||
}
|
||||
localtime_r(&nowt,&now);
|
||||
daydiff = now.tm_yday - tm.tm_yday;
|
||||
if ((daydiff < 0) || (daydiff > 6)) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
CC=gcc
|
||||
#CFLAGS=-Wall
|
||||
INCLUDE=-I../include
|
||||
|
||||
all: localtime.o
|
||||
|
||||
clean::
|
||||
rm -f localtime.o test
|
||||
|
||||
depend::
|
||||
@echo "Nothing to do for depend"
|
||||
|
||||
test: test.c
|
||||
${CC} ${CFLAGS} -o test test.c
|
||||
|
||||
localtime.o: localtime.c
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,220 @@
|
|||
/* $FreeBSD: src/lib/libc/stdtime/private.h,v 1.6.8.1 2000/08/23 00:19:15 jhb Exp $ */
|
||||
|
||||
#ifndef PRIVATE_H
|
||||
|
||||
#define PRIVATE_H
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
/* Stuff moved from Makefile.inc to reduce clutter */
|
||||
#ifndef TM_GMTOFF
|
||||
#define TM_GMTOFF tm_gmtoff
|
||||
#define TM_ZONE tm_zone
|
||||
#define STD_INSPIRED 1
|
||||
#define PCTS 1
|
||||
#define HAVE_LONG_DOUBLE 1
|
||||
#define HAVE_STRERROR 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define LOCALE_HOME _PATH_LOCALE
|
||||
#define TZDIR "/usr/share/zoneinfo"
|
||||
#endif /* ndef TM_GMTOFF */
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
** or that it will remain at all.
|
||||
** Do NOT copy it to any system include directory.
|
||||
** Thank you!
|
||||
*/
|
||||
|
||||
/*
|
||||
** ID
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
/*
|
||||
static char privatehid[] = "@(#)private.h 7.43";
|
||||
*/
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*
|
||||
** Defaults for preprocessor symbols.
|
||||
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ADJTIME
|
||||
#define HAVE_ADJTIME 1
|
||||
#endif /* !defined HAVE_ADJTIME */
|
||||
|
||||
#ifndef HAVE_GETTEXT
|
||||
#define HAVE_GETTEXT 0
|
||||
#endif /* !defined HAVE_GETTEXT */
|
||||
|
||||
#ifndef HAVE_SETTIMEOFDAY
|
||||
#define HAVE_SETTIMEOFDAY 3
|
||||
#endif /* !defined HAVE_SETTIMEOFDAY */
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
#define HAVE_STRERROR 0
|
||||
#endif /* !defined HAVE_STRERROR */
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H 1
|
||||
#endif /* !defined HAVE_UNISTD_H */
|
||||
|
||||
#ifndef HAVE_UTMPX_H
|
||||
#define HAVE_UTMPX_H 0
|
||||
#endif /* !defined HAVE_UTMPX_H */
|
||||
|
||||
#ifndef LOCALE_HOME
|
||||
#define LOCALE_HOME "/usr/lib/locale"
|
||||
#endif /* !defined LOCALE_HOME */
|
||||
|
||||
/*
|
||||
** Nested includes
|
||||
*/
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT */
|
||||
#include "time.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#if HAVE_GETTEXT - 0
|
||||
#include "libintl.h"
|
||||
#endif /* HAVE_GETTEXT - 0 */
|
||||
|
||||
#if HAVE_UNISTD_H - 0
|
||||
#include "unistd.h" /* for F_OK and R_OK */
|
||||
#endif /* HAVE_UNISTD_H - 0 */
|
||||
|
||||
#if !(HAVE_UNISTD_H - 0)
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif /* !defined F_OK */
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif /* !defined R_OK */
|
||||
#endif /* !(HAVE_UNISTD_H - 0) */
|
||||
|
||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||
|
||||
/*
|
||||
** Workarounds for compilers/systems.
|
||||
*/
|
||||
|
||||
#ifndef P
|
||||
#ifdef __STDC__
|
||||
#define P(x) x
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
#define P(x) ()
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined P */
|
||||
|
||||
/*
|
||||
** SunOS 4.1.1 headers lack FILENAME_MAX.
|
||||
*/
|
||||
|
||||
#ifndef FILENAME_MAX
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#ifdef unix
|
||||
#include "sys/param.h"
|
||||
#endif /* defined unix */
|
||||
#endif /* !defined MAXPATHLEN */
|
||||
|
||||
#ifdef MAXPATHLEN
|
||||
#define FILENAME_MAX MAXPATHLEN
|
||||
#endif /* defined MAXPATHLEN */
|
||||
#ifndef MAXPATHLEN
|
||||
#define FILENAME_MAX 1024 /* Pure guesswork */
|
||||
#endif /* !defined MAXPATHLEN */
|
||||
|
||||
#endif /* !defined FILENAME_MAX */
|
||||
|
||||
/*
|
||||
** Finally, some convenience items.
|
||||
*/
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* !defined TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* !defined FALSE */
|
||||
|
||||
#ifndef TYPE_BIT
|
||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||
#endif /* !defined TYPE_BIT */
|
||||
|
||||
#ifndef TYPE_SIGNED
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#endif /* !defined TYPE_SIGNED */
|
||||
|
||||
#ifndef INT_STRLEN_MAXIMUM
|
||||
/*
|
||||
** 302 / 1000 is log10(2.0) rounded up.
|
||||
** Subtract one for the sign bit if the type is signed;
|
||||
** add one for integer division truncation;
|
||||
** add one more for a minus sign if the type is signed.
|
||||
*/
|
||||
#define INT_STRLEN_MAXIMUM(type) \
|
||||
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
|
||||
#endif /* !defined INT_STRLEN_MAXIMUM */
|
||||
|
||||
/*
|
||||
** INITIALIZE(x)
|
||||
*/
|
||||
|
||||
#ifndef GNUC_or_lint
|
||||
#ifdef lint
|
||||
#define GNUC_or_lint
|
||||
#endif /* defined lint */
|
||||
#ifndef lint
|
||||
#ifdef __GNUC__
|
||||
#define GNUC_or_lint
|
||||
#endif /* defined __GNUC__ */
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined GNUC_or_lint */
|
||||
|
||||
#ifndef INITIALIZE
|
||||
#ifdef GNUC_or_lint
|
||||
#define INITIALIZE(x) ((x) = 0)
|
||||
#endif /* defined GNUC_or_lint */
|
||||
#ifndef GNUC_or_lint
|
||||
#define INITIALIZE(x)
|
||||
#endif /* !defined GNUC_or_lint */
|
||||
#endif /* !defined INITIALIZE */
|
||||
|
||||
/*
|
||||
** For the benefit of GNU folk...
|
||||
** `_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** The default is to use gettext if available, and use MSGID otherwise.
|
||||
*/
|
||||
|
||||
#ifndef _
|
||||
#if HAVE_GETTEXT - 0
|
||||
#define _(msgid) gettext(msgid)
|
||||
#else /* !(HAVE_GETTEXT - 0) */
|
||||
#define _(msgid) msgid
|
||||
#endif /* !(HAVE_GETTEXT - 0) */
|
||||
#endif /* !defined _ */
|
||||
|
||||
#ifndef TZ_DOMAIN
|
||||
#define TZ_DOMAIN "tz"
|
||||
#endif /* !defined TZ_DOMAIN */
|
||||
|
||||
/*
|
||||
** UNIX was a registered trademark of UNIX System Laboratories in 1993.
|
||||
*/
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
|
@ -0,0 +1,20 @@
|
|||
/* Testing localtime functionality */
|
||||
|
||||
#include "localtime.c"
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
char *zone[4] = { "America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles" };
|
||||
int i;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
|
||||
for (i=0;i<4;i++) {
|
||||
ast_localtime(&tv.tv_sec,&tm,zone[i]);
|
||||
printf("Localtime at %s is %04d/%02d/%02d %02d:%02d:%02d\n",zone[i],tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
#ifndef TZFILE_H
|
||||
|
||||
#define TZFILE_H
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
** or that it will remain at all.
|
||||
** Do NOT copy it to any system include directory.
|
||||
** Thank you!
|
||||
*/
|
||||
|
||||
/*
|
||||
** ID
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
/*
|
||||
static char tzfilehid[] = "@(#)tzfile.h 7.14";
|
||||
*/
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*
|
||||
** Information about time zone files.
|
||||
*/
|
||||
|
||||
#ifndef TZDIR
|
||||
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
|
||||
#endif /* !defined TZDIR */
|
||||
|
||||
#ifndef TZDEFAULT
|
||||
#define TZDEFAULT "/etc/localtime"
|
||||
#endif /* !defined TZDEFAULT */
|
||||
|
||||
#ifndef TZDEFRULES
|
||||
#define TZDEFRULES "posixrules"
|
||||
#endif /* !defined TZDEFRULES */
|
||||
|
||||
/*
|
||||
** Each file begins with. . .
|
||||
*/
|
||||
|
||||
#define TZ_MAGIC "TZif"
|
||||
|
||||
struct tzhead {
|
||||
char tzh_magic[4]; /* TZ_MAGIC */
|
||||
char tzh_reserved[16]; /* reserved for future use */
|
||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||
char tzh_timecnt[4]; /* coded number of transition times */
|
||||
char tzh_typecnt[4]; /* coded number of local time types */
|
||||
char tzh_charcnt[4]; /* coded number of abbr. chars */
|
||||
};
|
||||
|
||||
/*
|
||||
** . . .followed by. . .
|
||||
**
|
||||
** tzh_timecnt (char [4])s coded transition times a la time(2)
|
||||
** tzh_timecnt (unsigned char)s types of local time starting at above
|
||||
** tzh_typecnt repetitions of
|
||||
** one (char [4]) coded UTC offset in seconds
|
||||
** one (unsigned char) used to set tm_isdst
|
||||
** one (unsigned char) that's an abbreviation list index
|
||||
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
|
||||
** tzh_leapcnt repetitions of
|
||||
** one (char [4]) coded leap second transition times
|
||||
** one (char [4]) total correction after above
|
||||
** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is standard time, if FALSE,
|
||||
** transition time is wall clock time
|
||||
** if absent, transition times are
|
||||
** assumed to be wall clock time
|
||||
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is UTC, if FALSE,
|
||||
** transition time is local time
|
||||
** if absent, transition times are
|
||||
** assumed to be local time
|
||||
*/
|
||||
|
||||
/*
|
||||
** In the current implementation, "tzset()" refuses to deal with files that
|
||||
** exceed any of the limits below.
|
||||
*/
|
||||
|
||||
#ifndef TZ_MAX_TIMES
|
||||
/*
|
||||
** The TZ_MAX_TIMES value below is enough to handle a bit more than a
|
||||
** year's worth of solar time (corrected daily to the nearest second) or
|
||||
** 138 years of Pacific Presidential Election time
|
||||
** (where there are three time zone transitions every fourth year).
|
||||
*/
|
||||
#define TZ_MAX_TIMES 370
|
||||
#endif /* !defined TZ_MAX_TIMES */
|
||||
|
||||
#ifndef TZ_MAX_TYPES
|
||||
#ifndef NOSOLAR
|
||||
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#ifdef NOSOLAR
|
||||
/*
|
||||
** Must be at least 14 for Europe/Riga as of Jan 12 1995,
|
||||
** as noted by Earl Chew <earl@hpato.aus.hp.com>.
|
||||
*/
|
||||
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#endif /* !defined TZ_MAX_TYPES */
|
||||
|
||||
#ifndef TZ_MAX_CHARS
|
||||
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
|
||||
/* (limited by what unsigned chars can hold) */
|
||||
#endif /* !defined TZ_MAX_CHARS */
|
||||
|
||||
#ifndef TZ_MAX_LEAPS
|
||||
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
|
||||
#endif /* !defined TZ_MAX_LEAPS */
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define DAYSPERWEEK 7
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define TM_SUNDAY 0
|
||||
#define TM_MONDAY 1
|
||||
#define TM_TUESDAY 2
|
||||
#define TM_WEDNESDAY 3
|
||||
#define TM_THURSDAY 4
|
||||
#define TM_FRIDAY 5
|
||||
#define TM_SATURDAY 6
|
||||
|
||||
#define TM_JANUARY 0
|
||||
#define TM_FEBRUARY 1
|
||||
#define TM_MARCH 2
|
||||
#define TM_APRIL 3
|
||||
#define TM_MAY 4
|
||||
#define TM_JUNE 5
|
||||
#define TM_JULY 6
|
||||
#define TM_AUGUST 7
|
||||
#define TM_SEPTEMBER 8
|
||||
#define TM_OCTOBER 9
|
||||
#define TM_NOVEMBER 10
|
||||
#define TM_DECEMBER 11
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY TM_THURSDAY
|
||||
|
||||
/*
|
||||
** Accurate only for the past couple of centuries;
|
||||
** that will probably do.
|
||||
*/
|
||||
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
|
||||
#ifndef USG
|
||||
|
||||
/*
|
||||
** Use of the underscored variants may cause problems if you move your code to
|
||||
** certain System-V-based systems; for maximum portability, use the
|
||||
** underscore-free variants. The underscored variants are provided for
|
||||
** backward compatibility only; they may disappear from future versions of
|
||||
** this file.
|
||||
*/
|
||||
|
||||
#define SECS_PER_MIN SECSPERMIN
|
||||
#define MINS_PER_HOUR MINSPERHOUR
|
||||
#define HOURS_PER_DAY HOURSPERDAY
|
||||
#define DAYS_PER_WEEK DAYSPERWEEK
|
||||
#define DAYS_PER_NYEAR DAYSPERNYEAR
|
||||
#define DAYS_PER_LYEAR DAYSPERLYEAR
|
||||
#define SECS_PER_HOUR SECSPERHOUR
|
||||
#define SECS_PER_DAY SECSPERDAY
|
||||
#define MONS_PER_YEAR MONSPERYEAR
|
||||
|
||||
#endif /* !defined USG */
|
||||
|
||||
#endif /* !defined TZFILE_H */
|
Loading…
Reference in New Issue