Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Enumerations | Functions | Variables
app_directory.c File Reference

Provide a directory of extensions. More...

#include "asterisk.h"
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
Include dependency graph for app_directory.c:

Go to the source code of this file.

Data Structures

struct  directory_item
 
struct  itemlist
 

Macros

#define VOICEMAIL_CONFIG   "voicemail.conf"
 

Enumerations

enum  {
  OPT_LISTBYFIRSTNAME = (1 << 0) , OPT_SAYEXTENSION = (1 << 1) , OPT_FROMVOICEMAIL = (1 << 2) , OPT_SELECTFROMMENU = (1 << 3) ,
  OPT_LISTBYLASTNAME = (1 << 4) , OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME , OPT_PAUSE = (1 << 5) , OPT_NOANSWER = (1 << 6) ,
  OPT_ALIAS = (1 << 7)
}
 
enum  {
  OPT_ARG_FIRSTNAME = 0 , OPT_ARG_LASTNAME = 1 , OPT_ARG_EITHER = 2 , OPT_ARG_PAUSE = 3 ,
  OPT_ARG_ARRAY_SIZE = 4
}
 

Functions

static void __init_commonbuf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int check_match (struct directory_item **result, const char *item_context, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name)
 
static int compare (const char *text, const char *template)
 
static int directory_exec (struct ast_channel *chan, const char *data)
 
static int do_directory (struct ast_channel *chan, struct ast_config *vmcfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags, char *opts[])
 
static int goto_exten (struct ast_channel *chan, const char *dialcontext, char *ext)
 
static int load_module (void)
 
static int play_mailbox_owner (struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)
 
static struct ast_configrealtime_directory (char *context)
 
static int search_directory (const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int search_directory_sub (const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int select_entry (struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
 
static int select_item_menu (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static int select_item_pause (struct ast_channel *chan, struct ast_flags *flags, char *opts[])
 
static int select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static void sort_items (struct directory_item **sorted, int count)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "Directory"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
 
static const struct ast_app_option directory_app_options [128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, }
 

Detailed Description

Provide a directory of extensions.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_directory.c.

Macro Definition Documentation

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 144 of file app_directory.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_LISTBYFIRSTNAME 
OPT_SAYEXTENSION 
OPT_FROMVOICEMAIL 
OPT_SELECTFROMMENU 
OPT_LISTBYLASTNAME 
OPT_LISTBYEITHER 
OPT_PAUSE 
OPT_NOANSWER 
OPT_ALIAS 

Definition at line 146 of file app_directory.c.

146  {
147  OPT_LISTBYFIRSTNAME = (1 << 0),
148  OPT_SAYEXTENSION = (1 << 1),
149  OPT_FROMVOICEMAIL = (1 << 2),
150  OPT_SELECTFROMMENU = (1 << 3),
151  OPT_LISTBYLASTNAME = (1 << 4),
153  OPT_PAUSE = (1 << 5),
154  OPT_NOANSWER = (1 << 6),
155  OPT_ALIAS = (1 << 7),
156 };
@ OPT_LISTBYFIRSTNAME
@ OPT_LISTBYEITHER
@ OPT_NOANSWER
@ OPT_LISTBYLASTNAME
@ OPT_SAYEXTENSION
@ OPT_ALIAS
@ OPT_SELECTFROMMENU
@ OPT_PAUSE
@ OPT_FROMVOICEMAIL

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_FIRSTNAME 
OPT_ARG_LASTNAME 
OPT_ARG_EITHER 
OPT_ARG_PAUSE 
OPT_ARG_ARRAY_SIZE 

Definition at line 158 of file app_directory.c.

158  {
159  OPT_ARG_FIRSTNAME = 0,
160  OPT_ARG_LASTNAME = 1,
161  OPT_ARG_EITHER = 2,
162  OPT_ARG_PAUSE = 3,
163  /* This *must* be the last value in this enum! */
164  OPT_ARG_ARRAY_SIZE = 4,
165 };
@ OPT_ARG_LASTNAME
@ OPT_ARG_FIRSTNAME
@ OPT_ARG_PAUSE
@ OPT_ARG_ARRAY_SIZE
@ OPT_ARG_EITHER

Function Documentation

◆ __init_commonbuf()

static void __init_commonbuf ( void  )
static

Definition at line 459 of file app_directory.c.

462 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 992 of file app_directory.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 992 of file app_directory.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 992 of file app_directory.c.

◆ check_match()

static int check_match ( struct directory_item **  result,
const char *  item_context,
const char *  item_fullname,
const char *  item_ext,
const char *  pattern_ext,
int  use_first_name 
)
static

Definition at line 559 of file app_directory.c.

560 {
561  struct directory_item *item;
562  const char *key = NULL;
563  int namelen;
564 
565  if (ast_strlen_zero(item_fullname)) {
566  return 0;
567  }
568 
569  /* Set key to last name or first name depending on search mode */
570  if (!use_first_name)
571  key = strchr(item_fullname, ' ');
572 
573  if (key)
574  key++;
575  else
576  key = item_fullname;
577 
578  if (compare(key, pattern_ext))
579  return 0;
580 
581  ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
582 
583  /* Match */
584  item = ast_calloc(1, sizeof(*item));
585  if (!item)
586  return -1;
587  ast_copy_string(item->context, item_context, sizeof(item->context));
588  ast_copy_string(item->name, item_fullname, sizeof(item->name));
589  ast_copy_string(item->exten, item_ext, sizeof(item->exten));
590 
591  ast_copy_string(item->key, key, sizeof(item->key));
592  if (key != item_fullname) {
593  /* Key is the last name. Append first name to key in order to sort Last,First */
594  namelen = key - item_fullname - 1;
595  if (namelen > sizeof(item->key) - strlen(item->key) - 1)
596  namelen = sizeof(item->key) - strlen(item->key) - 1;
597  strncat(item->key, item_fullname, namelen);
598  }
599 
600  *result = item;
601  return 1;
602 }
static int compare(const char *text, const char *template)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static PGresult * result
Definition: cel_pgsql.c:84
#define ast_debug(level,...)
Log a DEBUG message.
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
const char * name
static struct aco_type item
Definition: test_config.c:1463

References ast_calloc, ast_copy_string(), ast_debug, ast_strlen_zero(), compare(), item, directory_item::key, aco_type::name, NULL, and result.

Referenced by search_directory_sub().

◆ compare()

static int compare ( const char *  text,
const char *  template 
)
static

Definition at line 188 of file app_directory.c.

189 {
190  char digit;
191 
192  if (ast_strlen_zero(text)) {
193  return -1;
194  }
195 
196  while (*template) {
197  digit = toupper(*text++);
198  switch (digit) {
199  case 0:
200  return -1;
201  case '1':
202  digit = '1';
203  break;
204  case '2':
205  case 'A':
206  case 'B':
207  case 'C':
208  digit = '2';
209  break;
210  case '3':
211  case 'D':
212  case 'E':
213  case 'F':
214  digit = '3';
215  break;
216  case '4':
217  case 'G':
218  case 'H':
219  case 'I':
220  digit = '4';
221  break;
222  case '5':
223  case 'J':
224  case 'K':
225  case 'L':
226  digit = '5';
227  break;
228  case '6':
229  case 'M':
230  case 'N':
231  case 'O':
232  digit = '6';
233  break;
234  case '7':
235  case 'P':
236  case 'Q':
237  case 'R':
238  case 'S':
239  digit = '7';
240  break;
241  case '8':
242  case 'T':
243  case 'U':
244  case 'V':
245  digit = '8';
246  break;
247  case '9':
248  case 'W':
249  case 'X':
250  case 'Y':
251  case 'Z':
252  digit = '9';
253  break;
254 
255  default:
256  if (digit > ' ')
257  return -1;
258  continue;
259  }
260 
261  if (*template++ != digit)
262  return -1;
263  }
264 
265  return 0;
266 }
char digit
char * text
Definition: app_queue.c:1641

References ast_strlen_zero(), digit, and text.

Referenced by _ast_hashtab_create(), ast_sip_is_content_type(), and check_match().

◆ directory_exec()

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

Definition at line 847 of file app_directory.c.

848 {
849  int res = 0, digit = 3;
850  struct ast_config *cfg, *ucfg;
851  const char *dirintro;
852  char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, };
853  struct ast_flags flags = { 0 };
854  struct ast_flags config_flags = { 0 };
855  enum { FIRST, LAST, BOTH } which = LAST;
856  char digits[9] = "digits/3";
858  AST_APP_ARG(vmcontext);
861  );
862 
863  parse = ast_strdupa(data);
864 
866 
867  if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
868  return -1;
869 
870  if (!(cfg = realtime_directory(args.vmcontext))) {
871  ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
872  return -1;
873  }
874 
875  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
876  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
877  ucfg = NULL;
878  }
879 
880  dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
881  if (ast_strlen_zero(dirintro))
882  dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
883  /* the above prompts probably should be modified to include 0 for dialing operator
884  and # for exiting (continues in dialplan) */
885 
887  if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) {
888  digit = atoi(opts[OPT_ARG_EITHER]);
889  }
890  which = BOTH;
891  } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
892  if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) {
893  digit = atoi(opts[OPT_ARG_FIRSTNAME]);
894  }
895  which = FIRST;
896  } else {
897  if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) {
898  digit = atoi(opts[OPT_ARG_LASTNAME]);
899  }
900  which = LAST;
901  }
902 
903  /* If no options specified, search by last name */
906  which = LAST;
907  }
908 
909  if (digit > 9) {
910  digit = 9;
911  } else if (digit < 1) {
912  digit = 3;
913  }
914  digits[7] = digit + '0';
915 
916  if (ast_channel_state(chan) != AST_STATE_UP) {
917  if (!ast_test_flag(&flags, OPT_NOANSWER)) {
918  /* Otherwise answer unless we're supposed to read while on-hook */
919  res = ast_answer(chan);
920  }
921  }
922  for (;;) {
923  if (!ast_strlen_zero(dirintro) && !res) {
924  res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
925  } else if (!res) {
926  /* Stop playing sounds as soon as we have a digit. */
927  res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY);
928  if (!res) {
929  res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY);
930  }
931  if (!res) {
932  res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY);
933  }
934  if (!res) {
935  res = ast_stream_and_wait(chan,
936  which == FIRST ? "dir-first" :
937  which == LAST ? "dir-last" :
938  "dir-firstlast", AST_DIGIT_ANY);
939  }
940  if (!res) {
941  res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY);
942  }
943  }
944  ast_stopstream(chan);
945  if (!res)
946  res = ast_waitfordigit(chan, 5000);
947 
948  if (res <= 0) {
949  if (res == 0) {
950  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "TIMEOUT");
951  }
952  break;
953  }
954 
955  res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts);
956  if (res)
957  break;
958 
959  res = ast_waitstream(chan, AST_DIGIT_ANY);
960  ast_stopstream(chan);
961  if (res < 0) {
962  break;
963  }
964  }
965 
966  if (ucfg)
967  ast_config_destroy(ucfg);
968  ast_config_destroy(cfg);
969 
970  if (ast_check_hangup(chan)) {
971  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "HANGUP");
972  } else if (res < 0) {
973  /* If the res < 0 and we didn't hangup, an unaccounted for error must have happened. */
974  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "FAILED");
975  }
976 
977  return res < 0 ? -1 : 0;
978 }
static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags, char *opts[])
static const struct ast_app_option directory_app_options[128]
static struct ast_config * realtime_directory(char *context)
static char dialcontext[AST_MAX_CONTEXT]
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1844
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3176
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2806
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1855
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1817
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
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:3126
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:768
#define LOG_ERROR
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.
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
const char * args
static struct test_options options
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70

References args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_check_hangup(), ast_config_destroy(), ast_config_load, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_log, ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), CONFIG_STATUS_FILEINVALID, dialcontext, digit, directory_app_options, do_directory(), ast_flags::flags, LOG_ERROR, NULL, OPT_ARG_ARRAY_SIZE, OPT_ARG_EITHER, OPT_ARG_FIRSTNAME, OPT_ARG_LASTNAME, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, OPT_NOANSWER, options, parse(), pbx_builtin_setvar_helper(), and realtime_directory().

◆ do_directory()

static int do_directory ( struct ast_channel chan,
struct ast_config vmcfg,
struct ast_config ucfg,
char *  context,
char *  dialcontext,
char  digit,
int  digits,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 768 of file app_directory.c.

769 {
770  /* Read in the first three digits.. "digit" is the first digit, already read */
771  int res = 0;
773  struct directory_item *item, **ptr, **sorted = NULL;
774  int count, i;
775  char ext[10] = "";
776 
777  if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
778  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
779  return digit;
780  }
781 
782  if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
783  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "ASSISTANT");
784  return digit;
785  }
786 
787  ext[0] = digit;
788  if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0)
789  return -1;
790 
791  res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist);
792  if (res)
793  goto exit;
794 
795  /* Count items in the list */
796  count = 0;
798  count++;
799  }
800 
801  if (count < 1) {
802  res = ast_streamfile(chan, "dir-nomatch", ast_channel_language(chan));
803  goto exit;
804  }
805 
806 
807  /* Create plain array of pointers to items (for sorting) */
808  sorted = ast_calloc(count, sizeof(*sorted));
809 
810  ptr = sorted;
812  *ptr++ = item;
813  }
814 
815  /* Sort items */
816  sort_items(sorted, count);
817 
818  if (DEBUG_ATLEAST(2)) {
819  ast_log(LOG_DEBUG, "Listing matching entries:\n");
820  for (ptr = sorted, i = 0; i < count; i++, ptr++) {
821  ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
822  }
823  }
824 
825  if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
826  /* Offer multiple entries at the same time */
827  res = select_item_menu(chan, sorted, count, dialcontext, flags, opts);
828  } else {
829  /* Offer entries one by one */
830  res = select_item_seq(chan, sorted, count, dialcontext, flags, opts);
831  }
832 
833  if (!res) {
834  res = ast_streamfile(chan, "dir-nomore", ast_channel_language(chan));
835  }
836 
837 exit:
838  if (sorted)
839  ast_free(sorted);
840 
841  while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
842  ast_free(item);
843 
844  return res;
845 }
static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
static void sort_items(struct directory_item **sorted, int count)
static int select_item_menu(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
static int search_directory(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
#define ast_free(a)
Definition: astmm.h:180
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
const char * ast_channel_language(const struct ast_channel *chan)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6636
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1291
static const char name[]
Definition: format_mp3.c:68
const char * ext
Definition: http.c:150
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Definition: f2c.h:129
Definition: search.h:40

References ast_calloc, ast_channel_language(), ast_free, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log, ast_readstring(), ast_streamfile(), ast_test_flag, context, DEBUG_ATLEAST, dialcontext, digit, ext, exten, goto_exten(), item, LOG_DEBUG, name, NULL, OPT_SELECTFROMMENU, pbx_builtin_setvar_helper(), search_directory(), select_item_menu(), select_item_seq(), and sort_items().

Referenced by directory_exec().

◆ goto_exten()

static int goto_exten ( struct ast_channel chan,
const char *  dialcontext,
char *  ext 
)
static

Definition at line 268 of file app_directory.c.

269 {
270  if (!ast_goto_if_exists(chan, S_OR(dialcontext, ast_channel_context(chan)), ext, 1) ||
272  !ast_goto_if_exists(chan, ast_channel_macrocontext(chan), ext, 1))) {
273  return 0;
274  } else {
275  ast_log(LOG_WARNING, "Can't find extension '%s' in current context. "
276  "Not Exiting the Directory!\n", ext);
277  return -1;
278  }
279 }
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_macrocontext(const struct ast_channel *chan)
#define LOG_WARNING
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80

References ast_channel_context(), ast_channel_macrocontext(), ast_goto_if_exists(), ast_log, ast_strlen_zero(), dialcontext, ext, LOG_WARNING, and S_OR.

Referenced by do_directory(), and select_item_seq().

◆ load_module()

static int load_module ( void  )
static

Definition at line 987 of file app_directory.c.

988 {
990 }
static const char app[]
static int directory_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ play_mailbox_owner()

static int play_mailbox_owner ( struct ast_channel chan,
const char *  context,
const char *  ext,
const char *  name,
struct ast_flags flags 
)
static

Definition at line 286 of file app_directory.c.

288 {
289  int res = 0;
290  char *mailbox_id;
291 
292  mailbox_id = ast_alloca(strlen(ext) + strlen(context) + 2);
293  sprintf(mailbox_id, "%s@%s", ext, context); /* Safe */
294 
295  res = ast_app_sayname(chan, mailbox_id);
296  if (res >= 0) {
297  ast_stopstream(chan);
298  /* If Option 'e' was specified, also read the extension number with the name */
299  if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
300  ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
302  }
303  } else {
306  ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
308  }
309  }
310 
311  return res;
312 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
Play a recorded user name for the mailbox to the specified channel.
Definition: main/app.c:707
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
Definition: channel.c:8354
@ AST_SAY_CASE_NONE
Definition: say.h:182

References ast_alloca, ast_app_sayname(), ast_channel_language(), AST_DIGIT_ANY, AST_SAY_CASE_NONE, ast_say_character_str(), ast_stopstream(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, context, ext, name, OPT_SAYEXTENSION, and S_OR.

Referenced by select_item_menu(), and select_item_seq().

◆ realtime_directory()

static struct ast_config* realtime_directory ( char *  context)
static

Definition at line 461 of file app_directory.c.

462 {
463  struct ast_config *cfg;
464  struct ast_config *rtdata = NULL;
465  struct ast_category *cat;
466  struct ast_variable *var;
467  char *category = NULL;
468  const char *fullname;
469  const char *hidefromdir, *searchcontexts = NULL;
470  struct ast_flags config_flags = { 0 };
471  struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
472 
473  if (!tmp) {
474  return NULL;
475  }
476 
477  /* Load flat file config. */
478  cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
479 
480  if (!cfg) {
481  /* Loading config failed. */
482  ast_log(LOG_WARNING, "Loading config failed.\n");
483  return NULL;
484  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
485  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", VOICEMAIL_CONFIG);
486  return NULL;
487  }
488 
489  /* Get realtime entries, categorized by their mailbox number
490  and present in the requested context */
491  if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) {
492  if (ast_true(searchcontexts)) {
493  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL);
494  context = NULL;
495  } else {
496  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL);
497  context = "default";
498  }
499  } else if (!ast_strlen_zero(context)) {
500  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
501  }
502 
503  /* if there are no results, just return the entries from the config file */
504  if (!rtdata) {
505  return cfg;
506  }
507 
508  while ((category = ast_category_browse(rtdata, category))) {
509  const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox");
510  const char *ctx = ast_variable_retrieve(rtdata, category, "context");
511 
512  if (ast_strlen_zero(mailbox)) {
513  ast_debug(3, "Skipping result with missing or empty mailbox\n");
514  continue;
515  }
516 
517  fullname = ast_variable_retrieve(rtdata, category, "fullname");
518  hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir");
519  if (ast_true(hidefromdir)) {
520  /* Skip hidden */
521  continue;
522  }
523 
524  /* password,Full Name,email,pager,options */
525  ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, ""));
526  if (ast_variable_retrieve(rtdata, category, "alias")) {
527  struct ast_variable *alias;
528  for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) {
529  if (!strcasecmp(alias->name, "alias")) {
530  ast_str_append(&tmp, 0, "|alias=%s", alias->value);
531  }
532  }
533  }
534 
535  /* Does the context exist within the config file? If not, make one */
536  if (!(cat = ast_category_get(cfg, ctx, NULL))) {
537  if (!(cat = ast_category_new_dynamic(ctx))) {
538  ast_log(LOG_WARNING, "Out of memory\n");
539  ast_config_destroy(cfg);
540  if (rtdata) {
541  ast_config_destroy(rtdata);
542  }
543  return NULL;
544  }
545  ast_category_append(cfg, cat);
546  }
547 
548  if ((var = ast_variable_new(mailbox, ast_str_buffer(tmp), ""))) {
549  ast_variable_append(cat, var);
550  } else {
551  ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
552  }
553  }
554  ast_config_destroy(rtdata);
555 
556  return cfg;
557 }
#define VOICEMAIL_CONFIG
#define var
Definition: ast_expr2f.c:614
static int tmp()
Definition: bt_open.c:389
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:207
#define SENTINEL
Definition: compiler.h:87
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3327
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3521
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2834
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_variable_new(name, value, filename)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1096
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1117
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1091
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:887
Support for dynamic strings.
Definition: strings.h:604
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Definition: term.c:57

References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new_dynamic, ast_config_destroy(), ast_config_load, ast_debug, ast_load_realtime_multientry(), ast_log, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ast_true(), ast_variable_append(), ast_variable_browse(), ast_variable_new, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, context, LOG_ERROR, LOG_WARNING, mailbox, ast_variable::name, ast_variable::next, NULL, S_OR, SENTINEL, tmp(), ast_variable::value, var, and VOICEMAIL_CONFIG.

Referenced by directory_exec().

◆ search_directory()

static int search_directory ( const char *  context,
struct ast_config vmcfg,
struct ast_config ucfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 717 of file app_directory.c.

718 {
719  const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts");
720  if (ast_strlen_zero(context)) {
721  if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) {
722  /* Browse each context for a match */
723  int res;
724  const char *catg;
725  for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) {
726  if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) {
727  continue;
728  }
729 
730  if ((res = search_directory_sub(catg, vmcfg, ucfg, ext, flags, alist))) {
731  return res;
732  }
733  }
734  return 0;
735  } else {
736  ast_debug(1, "Searching by category default\n");
737  return search_directory_sub("default", vmcfg, ucfg, ext, flags, alist);
738  }
739  } else {
740  /* Browse only the listed context for a match */
741  ast_debug(1, "Searching by category %s\n", context);
742  return search_directory_sub(context, vmcfg, ucfg, ext, flags, alist);
743  }
744 }
static int search_directory_sub(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)

References ast_category_browse(), ast_debug, ast_strlen_zero(), ast_true(), ast_variable_retrieve(), context, ext, NULL, and search_directory_sub().

Referenced by do_directory().

◆ search_directory_sub()

static int search_directory_sub ( const char *  context,
struct ast_config vmcfg,
struct ast_config ucfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 606 of file app_directory.c.

607 {
608  struct ast_variable *v;
609  struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
610  char *name;
611  char *options;
612  char *alias;
613  char *cat;
614  struct directory_item *item;
615  int res;
616 
617  if (!buf) {
618  return -1;
619  }
620 
621  ast_debug(2, "Pattern: %s\n", ext);
622 
623  for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
624  ast_str_set(&buf, 0, "%s", v->value);
626 
627  /* password,Full Name,email,pager,options */
628  strsep(&options, ","); /* Skip password */
629  name = strsep(&options, ","); /* Save full name */
630  strsep(&options, ","); /* Skip email */
631  strsep(&options, ","); /* Skip pager */
632  /* options is now the options field if it exists. */
633 
634  if (options && strcasestr(options, "hidefromdir=yes")) {
635  /* Ignore hidden */
636  continue;
637  }
638  if (ast_strlen_zero(name)) {
639  /* No name to compare against */
640  continue;
641  }
642 
643  res = 0;
644  if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
645  res = check_match(&item, context, name, v->name, ext, 0 /* use_first_name */);
646  }
647  if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
648  res = check_match(&item, context, name, v->name, ext, 1 /* use_first_name */);
649  }
650  if (!res && ast_test_flag(&flags, OPT_ALIAS)
651  && options && (alias = strcasestr(options, "alias="))) {
652  char *a;
653 
654  ast_debug(1, "Found alias: %s\n", alias);
655  while ((a = strsep(&alias, "|"))) {
656  if (!strncasecmp(a, "alias=", 6)) {
657  if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
658  break;
659  }
660  }
661  }
662  }
663 
664  if (!res) {
665  continue;
666  } else if (res < 0) {
667  return -1;
668  }
669 
671  }
672 
673  if (ucfg) {
674  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
675  const char *position;
676 
677  if (!strcasecmp(cat, "general")) {
678  continue;
679  }
680  if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) {
681  continue;
682  }
683 
684  /* Find all candidate extensions */
685  if (!(position = ast_variable_retrieve(ucfg, cat, "fullname"))) {
686  continue;
687  }
688 
689  res = 0;
690  if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
691  res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */);
692  }
693  if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
694  res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
695  }
696  if (!res && ast_test_flag(&flags, OPT_ALIAS)) {
697  for (v = ast_variable_browse(ucfg, cat); v; v = v->next) {
698  if (!strcasecmp(v->name, "alias")
699  && (res = check_match(&item, context, v->value, cat, ext, 1))) {
700  break;
701  }
702  }
703  }
704 
705  if (!res) {
706  continue;
707  } else if (res < 0) {
708  return -1;
709  }
710 
712  }
713  }
714  return 0;
715 }
static int check_match(struct directory_item **result, const char *item_context, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * strcasestr(const char *, const char *)
char * strsep(char **str, const char *delims)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
Definition: main/config.c:758
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
static struct test_val a

References a, ast_category_browse(), ast_config_option(), ast_debug, AST_LIST_INSERT_TAIL, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), context, ext, item, name, ast_variable::name, ast_variable::next, NULL, OPT_ALIAS, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, options, strcasestr(), strsep(), and ast_variable::value.

Referenced by search_directory().

◆ select_entry()

static int select_entry ( struct ast_channel chan,
const char *  dialcontext,
const struct directory_item item,
struct ast_flags flags 
)
static

Definition at line 314 of file app_directory.c.

315 {
316  ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context));
317 
318  if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
319  /* We still want to set the exten though */
320  ast_channel_exten_set(chan, item->exten);
321  } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) {
323  "Can't find extension '%s' in context '%s'. "
324  "Did you pass the wrong context to Directory?\n",
325  item->exten, S_OR(dialcontext, item->context));
326  return -1;
327  }
328 
329  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
330  return 0;
331 }
void ast_channel_exten_set(struct ast_channel *chan, const char *value)

References ast_channel_exten_set(), ast_debug, ast_goto_if_exists(), ast_log, ast_test_flag, dialcontext, item, LOG_WARNING, aco_type::name, OPT_FROMVOICEMAIL, pbx_builtin_setvar_helper(), and S_OR.

Referenced by select_item_menu(), and select_item_seq().

◆ select_item_menu()

static int select_item_menu ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 395 of file app_directory.c.

396 {
397  struct directory_item **block, *item;
398  int i, limit, res = 0;
399  char buf[7+12]; /* INT_MIN has a length of 12 chars */
400 
401  /* option p(n): cellphone pause option */
402  select_item_pause(chan, flags, opts);
403 
404  for (block = items; count; block += limit, count -= limit) {
405  limit = count;
406  if (limit > 8)
407  limit = 8;
408 
409  for (i = 0; i < limit && !res; i++) {
410  item = block[i];
411 
412  snprintf(buf, sizeof(buf), "digits/%d", i + 1);
413  /* Press <num> for <name>, [ extension <ext> ] */
414  res = ast_streamfile(chan, "dir-multi1", ast_channel_language(chan));
415  if (!res)
416  res = ast_waitstream(chan, AST_DIGIT_ANY);
417  if (!res)
418  res = ast_streamfile(chan, buf, ast_channel_language(chan));
419  if (!res)
420  res = ast_waitstream(chan, AST_DIGIT_ANY);
421  if (!res)
422  res = ast_streamfile(chan, "dir-multi2", ast_channel_language(chan));
423  if (!res)
424  res = ast_waitstream(chan, AST_DIGIT_ANY);
425  if (!res)
426  res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
427  if (!res)
428  res = ast_waitstream(chan, AST_DIGIT_ANY);
429  if (!res)
430  res = ast_waitfordigit(chan, 800);
431  }
432 
433  /* Press "9" for more names. */
434  if (!res && count > limit) {
435  res = ast_streamfile(chan, "dir-multi9", ast_channel_language(chan));
436  if (!res)
437  res = ast_waitstream(chan, AST_DIGIT_ANY);
438  }
439 
440  if (!res) {
441  res = ast_waitfordigit(chan, 3000);
442  }
443 
444  if (res && res > '0' && res < '1' + limit) {
445  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
446  return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1;
447  }
448 
449  if (res < 0)
450  return -1;
451 
452  res = 0;
453  }
454 
455  /* Nothing was selected */
456  return 0;
457 }
static int select_item_pause(struct ast_channel *chan, struct ast_flags *flags, char *opts[])
static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
static int play_mailbox_owner(struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)

References ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, dialcontext, item, aco_type::name, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

◆ select_item_pause()

static int select_item_pause ( struct ast_channel chan,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 333 of file app_directory.c.

334 {
335  int res = 0, opt_pause = 0;
336 
337  if (ast_test_flag(flags, OPT_PAUSE) && !ast_strlen_zero(opts[OPT_ARG_PAUSE])) {
338  opt_pause = atoi(opts[OPT_ARG_PAUSE]);
339  if (opt_pause > 3000) {
340  opt_pause = 3000;
341  }
342  res = ast_waitfordigit(chan, opt_pause);
343  }
344  return res;
345 }

References ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), OPT_ARG_PAUSE, and OPT_PAUSE.

Referenced by select_item_menu(), and select_item_seq().

◆ select_item_seq()

static int select_item_seq ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 347 of file app_directory.c.

348 {
349  struct directory_item *item, **ptr;
350  int i, res, loop;
351 
352  /* option p(n): cellphone pause option */
353  /* allow early press of selection key */
354  res = select_item_pause(chan, flags, opts);
355 
356  for (ptr = items, i = 0; i < count; i++, ptr++) {
357  item = *ptr;
358 
359  for (loop = 3 ; loop > 0; loop--) {
360  if (!res)
361  res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
362  if (!res)
363  res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
364  if (!res)
365  res = ast_waitfordigit(chan, 3000);
366  ast_stopstream(chan);
367 
368  if (res == '0') { /* operator selected */
369  goto_exten(chan, dialcontext, "o");
370  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
371  return '0';
372  } else if (res == '1') { /* Name selected */
373  return select_entry(chan, dialcontext, item, flags) ? -1 : 1;
374  } else if (res == '*') {
375  /* Skip to next match in list */
376  break;
377  } else if (res == '#') {
378  /* Exit reading, continue in dialplan */
379  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "USEREXIT");
380  return res;
381  }
382 
383  if (res < 0)
384  return -1;
385 
386  res = 0;
387  }
388  res = 0;
389  }
390 
391  /* Nothing was selected */
392  return 0;
393 }

References AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_waitfordigit(), dialcontext, goto_exten(), item, aco_type::name, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

◆ sort_items()

static void sort_items ( struct directory_item **  sorted,
int  count 
)
static

Definition at line 746 of file app_directory.c.

747 {
748  int reordered, i;
749  struct directory_item **ptr, *tmp;
750 
751  if (count < 2)
752  return;
753 
754  /* Bubble-sort items by the key */
755  do {
756  reordered = 0;
757  for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
758  if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
759  tmp = ptr[0];
760  ptr[0] = ptr[1];
761  ptr[1] = tmp;
762  reordered++;
763  }
764  }
765  } while (reordered);
766 }

References directory_item::key, and tmp().

Referenced by do_directory().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 980 of file app_directory.c.

981 {
982  int res;
984  return res;
985 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 987 of file app_directory.c.

◆ app

const char app[] = "Directory"
static

Definition at line 139 of file app_directory.c.

Referenced by unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 992 of file app_directory.c.

◆ commonbuf

struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
static

Definition at line 459 of file app_directory.c.

◆ directory_app_options

const struct ast_app_option directory_app_options[128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, }
static

Definition at line 139 of file app_directory.c.

Referenced by directory_exec().