Thu Apr 28 2011 16:56:52

Asterisk developer's documentation


app_readexten.c File Reference

Trivial application to read an extension into a variable. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/channel.h"
Include dependency graph for app_readexten.c:

Go to the source code of this file.

Enumerations

enum  { OPT_SKIP = (1 << 0), OPT_INDICATION = (1 << 1), OPT_NOANSWER = (1 << 2) }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int acf_isexten_exec (struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
static int load_module (void)
static int readexten_exec (struct ast_channel *chan, void *data)
static int unload_module (void)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Read and evaluate extension validity" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static struct ast_custom_function acf_isexten
static char * app = "ReadExten"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_app_option readexten_app_options [128] = { [ 's' ] = { .flag = OPT_SKIP }, [ 'i' ] = { .flag = OPT_INDICATION }, [ 'n' ] = { .flag = OPT_NOANSWER },}
enum { ... }  readexten_option_flags

Detailed Description

Trivial application to read an extension into a variable.

Author:
David Chappell <David.Chappell@trincoll.edu>

Definition in file app_readexten.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
OPT_SKIP 
OPT_INDICATION 
OPT_NOANSWER 

Definition at line 114 of file app_readexten.c.

     {
   OPT_SKIP = (1 << 0),
   OPT_INDICATION = (1 << 1),
   OPT_NOANSWER = (1 << 2),
} readexten_option_flags;

Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 315 of file app_readexten.c.

static void __unreg_module ( void  ) [static]

Definition at line 315 of file app_readexten.c.

static int acf_isexten_exec ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buffer,
size_t  buflen 
) [static]

Definition at line 263 of file app_readexten.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, and LOG_WARNING.

{
   int priority_int;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(context);
      AST_APP_ARG(extension);
      AST_APP_ARG(priority);
   );

   AST_STANDARD_APP_ARGS(args, parse);

   if (ast_strlen_zero(args.context))
      args.context = chan->context;

   if (ast_strlen_zero(args.extension)) {
      ast_log(LOG_WARNING, "Syntax: VALID_EXTEN([<context>],<extension>[,<priority>]) - missing argument <extension>!\n");
      return -1;
   }

   if (ast_strlen_zero(args.priority))
      priority_int = 1;
   else
      priority_int = atoi(args.priority);

   if (ast_exists_extension(chan, args.context, args.extension, priority_int, chan->cid.cid_num))
       ast_copy_string(buffer, "1", buflen);
   else
       ast_copy_string(buffer, "0", buflen);

   return 0;
}
static int load_module ( void  ) [static]
static int readexten_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 128 of file app_readexten.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_check_hangup(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_get_indication_tone(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_tone_zone_sound_unref(), ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, ast_tone_zone_sound::data, ast_pbx::dtimeoutms, exten, ast_channel::language, LOG_WARNING, ast_channel::name, OPT_INDICATION, OPT_NOANSWER, OPT_SKIP, ast_channel::pbx, pbx_builtin_setvar_helper(), readexten_app_options, ast_pbx::rtimeoutms, status, and ast_channel::zone.

Referenced by load_module().

{
   int res = 0;
   char exten[256] = "";
   int maxdigits = sizeof(exten) - 1;
   int timeout = 0, digit_timeout = 0, x = 0;
   char *argcopy = NULL, *status = "";
   struct ast_tone_zone_sound *ts = NULL;
   struct ast_flags flags = {0};

    AST_DECLARE_APP_ARGS(arglist,
      AST_APP_ARG(variable);
      AST_APP_ARG(filename);
      AST_APP_ARG(context);
      AST_APP_ARG(options);
      AST_APP_ARG(timeout);
   );
   
   if (ast_strlen_zero(data)) {
      ast_log(LOG_WARNING, "ReadExten requires at least one argument\n");
      pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
      return 0;
   }

   argcopy = ast_strdupa(data);
   AST_STANDARD_APP_ARGS(arglist, argcopy);

   if (ast_strlen_zero(arglist.variable)) {
      ast_log(LOG_WARNING, "Usage: ReadExten(variable[,filename[,context[,options[,timeout]]]])\n");
      pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
      return 0;
   }

   if (ast_strlen_zero(arglist.filename))
      arglist.filename = NULL;

   if (ast_strlen_zero(arglist.context))
      arglist.context = chan->context;

   if (!ast_strlen_zero(arglist.options))
      ast_app_parse_options(readexten_app_options, &flags, NULL, arglist.options);

   if (!ast_strlen_zero(arglist.timeout)) {
      timeout = atoi(arglist.timeout);
      if (timeout > 0)
         timeout *= 1000;
   }

   if (timeout <= 0)
      timeout = chan->pbx ? chan->pbx->rtimeoutms : 10000;

   if (digit_timeout <= 0)
      digit_timeout = chan->pbx ? chan->pbx->dtimeoutms : 5000;

   if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename)) {
      ts = ast_get_indication_tone(chan->zone, arglist.filename);
   }

   do {
      if (chan->_state != AST_STATE_UP) {
         if (ast_test_flag(&flags, OPT_SKIP)) {
            /* At the user's option, skip if the line is not up */
            pbx_builtin_setvar_helper(chan, arglist.variable, "");
            status = "SKIP";
            break;
         } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
            /* Otherwise answer unless we're supposed to read while on-hook */
            res = ast_answer(chan);
         }
      }

      if (res < 0) {
         status = "HANGUP";
         break;
      }

      ast_playtones_stop(chan);
      ast_stopstream(chan);

      if (ts && ts->data[0])
         res = ast_playtones_start(chan, 0, ts->data, 0);
      else if (arglist.filename)
         res = ast_streamfile(chan, arglist.filename, chan->language);

      for (x = 0; x < maxdigits; x++) {
         ast_debug(3, "extension so far: '%s', timeout: %d\n", exten, timeout);
         res = ast_waitfordigit(chan, timeout);

         ast_playtones_stop(chan);
         ast_stopstream(chan);
         timeout = digit_timeout;

         if (res < 1) {    /* timeout expired or hangup */
            if (ast_check_hangup(chan)) {
               status = "HANGUP";
            } else if (x == 0) {
               pbx_builtin_setvar_helper(chan, arglist.variable, "t");
               status = "TIMEOUT";
            }
            break;
         }

         exten[x] = res;
         if (!ast_matchmore_extension(chan, arglist.context, exten, 1 /* priority */, chan->cid.cid_num)) {
            if (!ast_exists_extension(chan, arglist.context, exten, 1, chan->cid.cid_num) && res == '#') {
               exten[x] = '\0';
            }
            break;
         }
      }

      if (!ast_strlen_zero(status))
         break;

      if (ast_exists_extension(chan, arglist.context, exten, 1, chan->cid.cid_num)) {
         ast_debug(3, "User entered valid extension '%s'\n", exten);
         pbx_builtin_setvar_helper(chan, arglist.variable, exten);
         status = "OK";
      } else {
         ast_debug(3, "User dialed invalid extension '%s' in context '%s' on %s\n", exten, arglist.context, chan->name);
         pbx_builtin_setvar_helper(chan, arglist.variable, "i");
         pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
         status = "INVALID";
      }
   } while (0);

   if (ts) {
      ts = ast_tone_zone_sound_unref(ts);
   }

   pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", status);

   return status[0] == 'H' ? -1 : 0;
}
static int unload_module ( void  ) [static]

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Read and evaluate extension validity" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 315 of file app_readexten.c.

Initial value:
 {
   .name = "VALID_EXTEN",
   .read = acf_isexten_exec,
}

Definition at line 295 of file app_readexten.c.

char* app = "ReadExten" [static]

Definition at line 126 of file app_readexten.c.

Definition at line 315 of file app_readexten.c.

struct ast_app_option readexten_app_options[128] = { [ 's' ] = { .flag = OPT_SKIP }, [ 'i' ] = { .flag = OPT_INDICATION }, [ 'n' ] = { .flag = OPT_NOANSWER },} [static]

Definition at line 124 of file app_readexten.c.

Referenced by readexten_exec().

enum { ... } readexten_option_flags