Asterisk - The Open Source Telephony Project  18.5.0
Enumerations | Functions | Variables
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  readexten_option_flags { OPT_SKIP = (1 << 0), OPT_INDICATION = (1 << 1), OPT_NOANSWER = (1 << 2), OPT_POUND_TO_END = (1 << 3) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static int readexten_exec (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Read and evaluate extension validity" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static char * app = "ReadExten"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option readexten_app_options [128] = { [ 's' ] = { .flag = OPT_SKIP }, [ 'i' ] = { .flag = OPT_INDICATION }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'p' ] = { .flag = OPT_POUND_TO_END }, }
 

Detailed Description

Trivial application to read an extension into a variable.

Author
David Chappell David.nosp@m..Cha.nosp@m.ppell.nosp@m.@tri.nosp@m.ncoll.nosp@m..edu

Definition in file app_readexten.c.

Enumeration Type Documentation

◆ readexten_option_flags

Enumerator
OPT_SKIP 
OPT_INDICATION 
OPT_NOANSWER 
OPT_POUND_TO_END 

Definition at line 103 of file app_readexten.c.

103  {
104  OPT_SKIP = (1 << 0),
105  OPT_INDICATION = (1 << 1),
106  OPT_NOANSWER = (1 << 2),
107  OPT_POUND_TO_END = (1 << 3),
108 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 288 of file app_readexten.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 288 of file app_readexten.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 288 of file app_readexten.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 282 of file app_readexten.c.

References ast_register_application_xml, and readexten_exec().

283 {
285  return res;
286 }
static int readexten_exec(struct ast_channel *chan, const char *data)
static char * app
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ readexten_exec()

static int readexten_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 119 of file app_readexten.c.

References ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_channel_caller(), ast_channel_context(), ast_channel_language(), ast_channel_name(), ast_channel_pbx(), ast_channel_zone(), ast_check_hangup(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), ast_fileexists(), 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(), context, ast_tone_zone_sound::data, ast_pbx::dtimeoutms, exten, LOG_WARNING, NULL, OPT_INDICATION, OPT_NOANSWER, OPT_POUND_TO_END, OPT_SKIP, options, pbx_builtin_setvar_helper(), readexten_app_options, ast_pbx::rtimeoutms, S_COR, status, and timeout.

Referenced by load_module().

120 {
121  int res = 0;
122  char exten[256] = "";
123  int maxdigits = sizeof(exten) - 1;
124  int timeout = 0, digit_timeout = 0, x = 0;
125  char *argcopy = NULL, *status = "";
126  struct ast_tone_zone_sound *ts = NULL;
127  struct ast_flags flags = {0};
128 
129  AST_DECLARE_APP_ARGS(arglist,
130  AST_APP_ARG(variable);
131  AST_APP_ARG(filename);
134  AST_APP_ARG(timeout);
135  );
136 
137  if (ast_strlen_zero(data)) {
138  ast_log(LOG_WARNING, "ReadExten requires at least one argument\n");
139  pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
140  return 0;
141  }
142 
143  argcopy = ast_strdupa(data);
144  AST_STANDARD_APP_ARGS(arglist, argcopy);
145 
146  if (ast_strlen_zero(arglist.variable)) {
147  ast_log(LOG_WARNING, "Usage: ReadExten(variable[,filename[,context[,options[,timeout]]]])\n");
148  pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
149  return 0;
150  }
151 
152  if (ast_strlen_zero(arglist.filename)) {
153  arglist.filename = NULL;
154  }
155 
156  if (ast_strlen_zero(arglist.context)) {
157  arglist.context = ast_strdupa(ast_channel_context(chan));
158  }
159 
160  if (!ast_strlen_zero(arglist.options)) {
161  ast_app_parse_options(readexten_app_options, &flags, NULL, arglist.options);
162  }
163 
164  if (!ast_strlen_zero(arglist.timeout)) {
165  timeout = atoi(arglist.timeout);
166  if (timeout > 0)
167  timeout *= 1000;
168  }
169 
170  if (timeout <= 0)
171  timeout = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 10000;
172 
173  digit_timeout = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
174 
175  if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename)) {
176  ts = ast_get_indication_tone(ast_channel_zone(chan), arglist.filename);
177  }
178 
179  do {
180  if (ast_channel_state(chan) != AST_STATE_UP) {
181  if (ast_test_flag(&flags, OPT_SKIP)) {
182  /* At the user's option, skip if the line is not up */
183  pbx_builtin_setvar_helper(chan, arglist.variable, "");
184  status = "SKIP";
185  break;
186  } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
187  /* Otherwise answer unless we're supposed to read while on-hook */
188  res = ast_answer(chan);
189  }
190  }
191 
192  if (res < 0) {
193  status = "HANGUP";
194  break;
195  }
196 
197  ast_playtones_stop(chan);
198  ast_stopstream(chan);
199 
200  if (ts && ts->data[0]) {
201  res = ast_playtones_start(chan, 0, ts->data, 0);
202  } else if (arglist.filename) {
203  if (ast_test_flag(&flags, OPT_INDICATION) && ast_fileexists(arglist.filename, NULL, ast_channel_language(chan)) <= 0) {
204  /*
205  * We were asked to play an indication that did not exist in the config.
206  * If no such file exists, play it as a tonelist. With any luck they won't
207  * have a file named "350+440.ulaw"
208  * (but honestly, who would do something so silly?)
209  */
210  res = ast_playtones_start(chan, 0, arglist.filename, 0);
211  } else {
212  res = ast_streamfile(chan, arglist.filename, ast_channel_language(chan));
213  }
214  }
215 
216  for (x = 0; x < maxdigits; x++) {
217  ast_debug(3, "extension so far: '%s', timeout: %d\n", exten, timeout);
218  res = ast_waitfordigit(chan, timeout);
219 
220  ast_playtones_stop(chan);
221  ast_stopstream(chan);
222  timeout = digit_timeout;
223 
224  if (res < 1) { /* timeout expired or hangup */
225  if (ast_check_hangup(chan)) {
226  status = "HANGUP";
227  } else if (x == 0) {
228  pbx_builtin_setvar_helper(chan, arglist.variable, "t");
229  status = "TIMEOUT";
230  }
231  break;
232  }
233 
234  if (ast_test_flag(&flags, OPT_POUND_TO_END) && res == '#') {
235  exten[x] = 0;
236  break;
237  }
238 
239  exten[x] = res;
240  if (!ast_matchmore_extension(chan, arglist.context, exten, 1 /* priority */,
241  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
242  if (!ast_exists_extension(chan, arglist.context, exten, 1,
243  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
244  && res == '#') {
245  exten[x] = '\0';
246  }
247  break;
248  }
249  }
250 
251  if (!ast_strlen_zero(status))
252  break;
253 
254  if (ast_exists_extension(chan, arglist.context, exten, 1,
255  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
256  ast_debug(3, "User entered valid extension '%s'\n", exten);
257  pbx_builtin_setvar_helper(chan, arglist.variable, exten);
258  status = "OK";
259  } else {
260  ast_debug(3, "User dialed invalid extension '%s' in context '%s' on %s\n", exten, arglist.context, ast_channel_name(chan));
261  pbx_builtin_setvar_helper(chan, arglist.variable, "i");
262  pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
263  status = "INVALID";
264  }
265  } while (0);
266 
267  if (ts) {
268  ts = ast_tone_zone_sound_unref(ts);
269  }
270 
271  pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", status);
272 
273  return status[0] == 'H' ? -1 : 0;
274 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4199
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static const struct ast_app_option readexten_app_options[128]
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
unsigned int flags
Definition: utils.h:200
struct ast_tone_zone * ast_channel_zone(const struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:227
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
Description of a tone.
Definition: indications.h:35
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:455
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
int dtimeoutms
Definition: pbx.h:212
const char * ast_channel_name(const struct ast_channel *chan)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
const char * ast_channel_language(const struct ast_channel *chan)
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
const char * ast_channel_context(const struct ast_channel *chan)
const char * data
Description of a tone.
Definition: indications.h:52
static struct test_options options
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
jack_status_t status
Definition: app_jack.c:146
#define AST_APP_ARG(name)
Define an application argument.
int rtimeoutms
Definition: pbx.h:213

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 276 of file app_readexten.c.

References ast_unregister_application().

277 {
278  int res = ast_unregister_application(app);
279  return res;
280 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * app

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Read and evaluate extension validity" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 288 of file app_readexten.c.

◆ app

char* app = "ReadExten"
static

Definition at line 117 of file app_readexten.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 288 of file app_readexten.c.

◆ readexten_app_options

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

Definition at line 115 of file app_readexten.c.

Referenced by readexten_exec().