diff options
-rw-r--r-- | include/asterisk/app.h | 17 | ||||
-rw-r--r-- | main/app.c | 56 | ||||
-rw-r--r-- | main/pbx.c | 14 |
3 files changed, 79 insertions, 8 deletions
diff --git a/include/asterisk/app.h b/include/asterisk/app.h index 6d73b7786..e2ec86328 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -84,6 +84,12 @@ struct ast_ivr_menu { static struct ast_ivr_option __options_##holder[] = foo;\ static struct ast_ivr_menu holder = { title, flags, __options_##holder } +typedef enum { + TIMELEN_HOURS, + TIMELEN_MINUTES, + TIMELEN_SECONDS, + TIMELEN_MILLISECONDS, +} ast_timelen; /*! \brief Runs an IVR menu \return returns 0 on successful completion, -1 on hangup, or -2 on user error in menu */ @@ -580,6 +586,17 @@ int ast_safe_fork(int stop_reaper); */ void ast_safe_fork_cleanup(void); +/*! + * \brief Common routine to parse time lengths, with optional time unit specifier + * \param[in] timestr String to parse + * \param[in] defunit Default unit type + * \param[out] result Resulting value, specified in milliseconds + * \retval 0 Success + * \retval -1 Failure + * \since 1.8 + */ +int ast_app_parse_timelen(const char *timestr, int *result, ast_timelen defunit); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/app.c b/main/app.c index 99dcfa677..580e91b76 100644 --- a/main/app.c +++ b/main/app.c @@ -2082,3 +2082,59 @@ void ast_safe_fork_cleanup(void) ast_unreplace_sigchld(); } +int ast_app_parse_timelen(const char *timestr, int *result, ast_timelen unit) +{ + int res; + char u[10]; +#ifdef HAVE_LONG_DOUBLE_WIDER + long double amount; + #define FMT "%30Lf%9s" +#else + double amount; + #define FMT "%30lf%9s" +#endif + if (!timestr) { + return -1; + } + + if ((res = sscanf(timestr, FMT, &amount, u)) == 0) { +#undef FMT + return -1; + } else if (res == 2) { + switch (u[0]) { + case 'h': + case 'H': + unit = TIMELEN_HOURS; + break; + case 's': + case 'S': + unit = TIMELEN_SECONDS; + break; + case 'm': + case 'M': + if (toupper(u[1]) == 'S') { + unit = TIMELEN_MILLISECONDS; + } else if (u[1] == '\0') { + unit = TIMELEN_MINUTES; + } + break; + } + } + + switch (unit) { + case TIMELEN_HOURS: + amount *= 60; + /* fall-through */ + case TIMELEN_MINUTES: + amount *= 60; + /* fall-through */ + case TIMELEN_SECONDS: + amount *= 1000; + /* fall-through */ + case TIMELEN_MILLISECONDS: + ; + } + *result = amount > INT_MAX ? INT_MAX : (int) amount; + return 0; +} + diff --git a/main/pbx.c b/main/pbx.c index dd2016ed2..58e689e54 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -9001,12 +9001,10 @@ static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data) */ static int pbx_builtin_wait(struct ast_channel *chan, const char *data) { - double s; int ms; /* Wait for "n" seconds */ - if (data && (s = atof(data)) > 0.0) { - ms = s * 1000.0; + if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) { return ast_safe_sleep(chan, ms); } return 0; @@ -9018,7 +9016,6 @@ static int pbx_builtin_wait(struct ast_channel *chan, const char *data) static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data) { int ms, res; - double s; struct ast_flags flags = {0}; char *opts[1] = { NULL }; char *parse; @@ -9050,12 +9047,13 @@ static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data) } } /* Wait for "n" seconds */ - if (args.timeout && (s = atof(args.timeout)) > 0) - ms = s * 1000.0; - else if (chan->pbx) + if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) { + /* Yay! */ + } else if (chan->pbx) { ms = chan->pbx->rtimeoutms; - else + } else { ms = 10000; + } res = ast_waitfordigit(chan, ms); if (!res) { |