summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/app.h17
-rw-r--r--main/app.c56
-rw-r--r--main/pbx.c14
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) {