major update to arg/option parsing APIs and documentation

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6953 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Kevin P. Fleming 20 years ago
parent fc9612edad
commit 426360e389

@ -1,3 +1,8 @@
2005-11-03 Kevin P. Fleming <kpfleming@digium.com>
* include/asterisk/app.h: re-work application arg/option parsing APIs for consistent naming, add doxygen docs for option API
* many files: update to new APIs
2005-11-02 Kevin P. Fleming <kpfleming@digium.com>
* apps/app_dial.c (dial_exec_full): convert to use API calls for argument/option parsing

23
app.c

@ -1105,7 +1105,7 @@ int ast_app_group_match_get_count(char *groupmatch, char *category)
return count;
}
int ast_separate_app_args(char *buf, char delim, char **array, int arraylen)
unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
{
int argc;
char *scan;
@ -1523,41 +1523,40 @@ char *ast_read_textfile(const char *filename)
return output;
}
int ast_parseoptions(const struct ast_option *options, struct ast_flags *flags, char **args, char *optstr)
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
{
char *s;
int curarg;
int argloc;
unsigned int argloc;
char *arg;
int res = 0;
flags->flags = 0;
ast_clear_flag(flags, AST_FLAGS_ALL);
if (!optstr)
return 0;
s = optstr;
while (*s) {
curarg = *s & 0x7f;
flags->flags |= options[curarg].flag;
curarg = *s++ & 0x7f;
ast_set_flag(flags, options[curarg].flag);
argloc = options[curarg].arg_index;
s++;
if (*s == '(') {
/* Has argument */
s++;
arg = s;
while (*s && (*s != ')')) s++;
while (*++s && (*s != ')'));
if (*s) {
if (argloc)
args[argloc - 1] = arg;
*s = '\0';
s++;
*s++ = '\0';
} else {
ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
res = -1;
}
} else if (argloc)
} else if (argloc) {
args[argloc - 1] = NULL;
}
}
return res;
}

@ -69,18 +69,27 @@ static const char *desc = " Chanspy([<scanspec>][|<options>])\n\n"
static const char *chanspy_spy_type = "ChanSpy";
#define OPTION_QUIET (1 << 0) /* Quiet, no announcement */
#define OPTION_BRIDGED (1 << 1) /* Only look at bridged calls */
#define OPTION_VOLUME (1 << 2) /* Specify initial volume */
#define OPTION_GROUP (1 << 3) /* Only look at channels in group */
#define OPTION_RECORD (1 << 4) /* Record */
AST_DECLARE_OPTIONS(chanspy_opts,{
['q'] = { OPTION_QUIET },
['b'] = { OPTION_BRIDGED },
['v'] = { OPTION_VOLUME, 1 },
['g'] = { OPTION_GROUP, 2 },
['r'] = { OPTION_RECORD, 3 },
enum {
OPTION_QUIET = (1 << 0), /* Quiet, no announcement */
OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */
OPTION_VOLUME = (1 << 2), /* Specify initial volume */
OPTION_GROUP = (1 << 3), /* Only look at channels in group */
OPTION_RECORD = (1 << 4), /* Record */
} chanspy_opt_flags;
enum {
OPT_ARG_VOLUME = 0,
OPT_ARG_GROUP,
OPT_ARG_RECORD,
OPT_ARG_ARRAY_SIZE,
} chanspy_opt_args;
AST_APP_OPTIONS(chanspy_opts, {
AST_APP_OPTION('q', OPTION_QUIET),
AST_APP_OPTION('b', OPTION_BRIDGED),
AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
});
STANDARD_LOCAL_USER;
@ -384,7 +393,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data)
ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
if ((argc = ast_separate_app_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
spec = argv[0];
if ( argc > 1) {
options = argv[1];
@ -395,8 +404,8 @@ static int chanspy_exec(struct ast_channel *chan, void *data)
}
if (options) {
char *opts[3];
ast_parseoptions(chanspy_opts, &flags, opts, options);
char *opts[OPT_ARG_ARRAY_SIZE];
ast_app_parse_options(chanspy_opts, &flags, opts, options);
if (ast_test_flag(&flags, OPTION_GROUP)) {
mygroup = opts[1];
}

@ -91,7 +91,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
tmp = ast_strdupa(data);
memset(argv, 0, sizeof(argv));
argc = ast_separate_app_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc < 1) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");

@ -160,7 +160,7 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
if (data) {
s = ast_strdupa((char *)data);
if (s) {
ast_separate_app_args(s, '|', args, 3);
ast_app_separate_args(s, '|', args, 3);
varname = args[0];
delimiter = args[1];
field = args[2];

@ -670,31 +670,31 @@ enum {
OPT_ARG_ARRAY_SIZE,
} dial_exec_option_args;
AST_DECLARE_OPTIONS(dial_exec_options, {
['A'] = { .flag = OPT_ANNOUNCE, .arg_index = OPT_ARG_ANNOUNCE + 1, },
['C'] = { .flag = OPT_RESETCDR, },
['d'] = { .flag = OPT_DTMF_EXIT, },
['D'] = { .flag = OPT_SENDDTMF, .arg_index = OPT_ARG_SENDDTMF + 1, },
['f'] = { .flag = OPT_FORCECLID, },
['g'] = { .flag = OPT_GO_ON, },
['G'] = { .flag = OPT_GOTO, .arg_index = OPT_ARG_GOTO + 1, },
['h'] = { .flag = OPT_CALLEE_HANGUP, },
['H'] = { .flag = OPT_CALLER_HANGUP, },
['j'] = { .flag = OPT_PRIORITY_JUMP, },
['L'] = { .flag = OPT_DURATION_LIMIT, .arg_index = OPT_ARG_DURATION_LIMIT + 1, },
['m'] = { .flag = OPT_MUSICBACK, .arg_index = OPT_ARG_MUSICBACK + 1, },
['M'] = { .flag = OPT_CALLEE_MACRO, .arg_index = OPT_ARG_CALLEE_MACRO + 1, },
['n'] = { .flag = OPT_SCREEN_NOINTRO, },
['N'] = { .flag = OPT_SCREEN_NOCLID, },
['o'] = { .flag = OPT_ORIGINAL_CLID, },
['p'] = { .flag = OPT_SCREENING, },
['P'] = { .flag = OPT_PRIVACY, .arg_index = OPT_ARG_PRIVACY + 1, },
['r'] = { .flag = OPT_RINGBACK, },
['S'] = { .flag = OPT_DURATION_STOP, .arg_index = OPT_ARG_DURATION_STOP + 1, },
['t'] = { .flag = OPT_CALLEE_TRANSFER, },
['T'] = { .flag = OPT_CALLER_TRANSFER, },
['w'] = { .flag = OPT_CALLEE_MONITOR, },
['W'] = { .flag = OPT_CALLER_MONITOR, },
AST_APP_OPTIONS(dial_exec_options, {
AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
AST_APP_OPTION('C', OPT_RESETCDR),
AST_APP_OPTION('d', OPT_DTMF_EXIT),
AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
AST_APP_OPTION('f', OPT_FORCECLID),
AST_APP_OPTION('g', OPT_GO_ON),
AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
AST_APP_OPTION('H', OPT_CALLER_HANGUP),
AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
AST_APP_OPTION('p', OPT_SCREENING),
AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
AST_APP_OPTION('r', OPT_RINGBACK),
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
AST_APP_OPTION('W', OPT_CALLER_MONITOR),
});
static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
@ -762,7 +762,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.options)) {
if (ast_parseoptions(dial_exec_options, &opts, opt_args, args.options)) {
if (ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) {
LOCAL_USER_REMOVE(u);
return -1;
}

@ -102,7 +102,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
if (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
argc = ast_separate_app_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
}
if (argc) {

@ -219,28 +219,28 @@ static void *recordthread(void *args);
#define CONFFLAG_ANNOUNCEUSERCOUNT (1 << 22) /* If set, when user joins the conference, they will be told the number of users that are already in */
AST_DECLARE_OPTIONS(meetme_opts,{
['a'] = { CONFFLAG_ADMIN },
['c'] = { CONFFLAG_ANNOUNCEUSERCOUNT },
['T'] = { CONFFLAG_MONITORTALKER },
['i'] = { CONFFLAG_INTROUSER },
['m'] = { CONFFLAG_MONITOR },
['p'] = { CONFFLAG_POUNDEXIT },
['s'] = { CONFFLAG_STARMENU },
['t'] = { CONFFLAG_TALKER },
['q'] = { CONFFLAG_QUIET },
['M'] = { CONFFLAG_MOH },
['x'] = { CONFFLAG_MARKEDEXIT },
['X'] = { CONFFLAG_EXIT_CONTEXT },
['A'] = { CONFFLAG_MARKEDUSER },
['b'] = { CONFFLAG_AGI },
['w'] = { CONFFLAG_WAITMARKED },
['r'] = { CONFFLAG_RECORDCONF },
['d'] = { CONFFLAG_DYNAMIC },
['D'] = { CONFFLAG_DYNAMICPIN },
['e'] = { CONFFLAG_EMPTY },
['E'] = { CONFFLAG_EMPTYNOPIN },
['P'] = { CONFFLAG_ALWAYSPROMPT },
AST_APP_OPTIONS(meetme_opts, {
AST_APP_OPTION('a', CONFFLAG_ADMIN ),
AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT ),
AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ),
AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
AST_APP_OPTION('m', CONFFLAG_MONITOR ),
AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ),
AST_APP_OPTION('s', CONFFLAG_STARMENU ),
AST_APP_OPTION('t', CONFFLAG_TALKER ),
AST_APP_OPTION('q', CONFFLAG_QUIET ),
AST_APP_OPTION('M', CONFFLAG_MOH ),
AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
AST_APP_OPTION('b', CONFFLAG_AGI ),
AST_APP_OPTION('w', CONFFLAG_WAITMARKED ),
AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
AST_APP_OPTION('d', CONFFLAG_DYNAMIC ),
AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ),
AST_APP_OPTION('e', CONFFLAG_EMPTY ),
AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ),
AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
});
static char *istalking(int x)
@ -1727,7 +1727,7 @@ static int conf_exec(struct ast_channel *chan, void *data)
ast_copy_string(the_pin, inpin, sizeof(the_pin));
if (inflags) {
ast_parseoptions(meetme_opts, &confflags, NULL, inflags);
ast_app_parse_options(meetme_opts, &confflags, NULL, inflags);
dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN);
if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !inpin)
strcpy(the_pin, "q");

@ -85,19 +85,26 @@ struct mixmonitor {
};
enum {
MUXFLAG_APPEND = (1 << 1),
MUXFLAG_BRIDGED = (1 << 2),
MUXFLAG_VOLUME = (1 << 3),
MUXFLAG_READVOLUME = (1 << 4),
MUXFLAG_WRITEVOLUME = (1 << 5),
MUXFLAG_APPEND = (1 << 1),
MUXFLAG_BRIDGED = (1 << 2),
MUXFLAG_VOLUME = (1 << 3),
MUXFLAG_READVOLUME = (1 << 4),
MUXFLAG_WRITEVOLUME = (1 << 5),
} mixmonitor_flags;
AST_DECLARE_OPTIONS(mixmonitor_opts,{
['a'] = { MUXFLAG_APPEND },
['b'] = { MUXFLAG_BRIDGED },
['v'] = { MUXFLAG_READVOLUME, 1 },
['V'] = { MUXFLAG_WRITEVOLUME, 2 },
['W'] = { MUXFLAG_VOLUME, 3 },
enum {
OPT_ARG_READVOLUME = 0,
OPT_ARG_WRITEVOLUME,
OPT_ARG_VOLUME,
OPT_ARG_ARRAY_SIZE,
} mixmonitor_args;
AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION('a', MUXFLAG_APPEND),
AST_APP_OPTION('b', MUXFLAG_BRIDGED),
AST_APP_OPTION_ARG('v', MUXFLAG_READVOLUME, OPT_ARG_READVOLUME),
AST_APP_OPTION_ARG('V', MUXFLAG_WRITEVOLUME, OPT_ARG_WRITEVOLUME),
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
});
static void stopmon(struct ast_channel *chan, struct ast_channel_spy *spy)
@ -331,35 +338,35 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
}
if (args.options) {
char *opts[3] = { NULL, };
char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
ast_parseoptions(mixmonitor_opts, &flags, opts, args.options);
ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
if (ast_strlen_zero(opts[0])) {
if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
} else if ((sscanf(opts[0], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[0]);
} else if ((sscanf(opts[OPT_ARG_READVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
} else {
readvol = get_volfactor(x);
}
}
if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
if (ast_strlen_zero(opts[1])) {
if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
} else if ((sscanf(opts[1], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[1]);
} else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
} else {
writevol = get_volfactor(x);
}
}
if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
if (ast_strlen_zero(opts[2])) {
if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
} else if ((sscanf(opts[2], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[2]);
} else if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
} else {
readvol = writevol = get_volfactor(x);
}

@ -61,12 +61,14 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define PAGE_DUPLEX (1 << 0)
#define PAGE_QUIET (1 << 1)
AST_DECLARE_OPTIONS(page_opts,{
['d'] = { PAGE_DUPLEX },
['q'] = { PAGE_QUIET },
enum {
PAGE_DUPLEX = (1 << 0),
PAGE_QUIET = (1 << 1),
} page_opt_flags;
AST_APP_OPTIONS(page_opts, {
AST_APP_OPTION('d', PAGE_DUPLEX),
AST_APP_OPTION('q', PAGE_QUIET),
});
struct calloutdata {
@ -142,7 +144,7 @@ static int page_exec(struct ast_channel *chan, void *data)
tmp = strsep(&options, "|");
if (options)
ast_parseoptions(page_opts, &flags, NULL, options);
ast_app_parse_options(page_opts, &flags, NULL, options);
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
while ((tech = strsep(&tmp, "&"))) {

@ -103,7 +103,7 @@ static int read_exec(struct ast_channel *chan, void *data)
return -1;
}
if (ast_separate_app_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
LOCAL_USER_REMOVE(u);
return -1;

@ -107,21 +107,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define ERROR_LOCK_PATH -100
#define OPT_SILENT (1 << 0)
#define OPT_BUSY_GREETING (1 << 1)
#define OPT_UNAVAIL_GREETING (1 << 2)
#define OPT_RECORDGAIN (1 << 3)
#define OPT_PREPEND_MAILBOX (1 << 4)
#define OPT_ARG_RECORDGAIN 0
#define OPT_ARG_ARRAY_SIZE 1
AST_DECLARE_OPTIONS(vm_app_options, {
['s'] = { .flag = OPT_SILENT },
['b'] = { .flag = OPT_BUSY_GREETING },
['u'] = { .flag = OPT_UNAVAIL_GREETING },
['g'] = { .flag = OPT_RECORDGAIN, .arg_index = OPT_ARG_RECORDGAIN + 1},
['p'] = { .flag = OPT_PREPEND_MAILBOX },
enum {
OPT_SILENT =(1 << 0),
OPT_BUSY_GREETING = (1 << 1),
OPT_UNAVAIL_GREETING = (1 << 2),
OPT_RECORDGAIN = (1 << 3),
OPT_PREPEND_MAILBOX = (1 << 4),
} vm_option_flags;
enum {
OPT_ARG_RECORDGAIN = 0,
OPT_ARG_ARRAY_SIZE = 1,
} vm_option_args;
AST_APP_OPTIONS(vm_app_options, {
AST_APP_OPTION('s', OPT_SILENT),
AST_APP_OPTION('b', OPT_BUSY_GREETING),
AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
});
static int load_config(void);
@ -5033,9 +5037,9 @@ static int vm_execmain(struct ast_channel *chan, void *data)
char *opts[OPT_ARG_ARRAY_SIZE];
tmp = ast_strdupa(data);
argc = ast_separate_app_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc == 2) {
if (ast_parseoptions(vm_app_options, &flags, opts, argv[1])) {
if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
LOCAL_USER_REMOVE(u);
return -1;
}
@ -5460,9 +5464,9 @@ static int vm_exec(struct ast_channel *chan, void *data)
if (!ast_strlen_zero(data)) {
ast_copy_string(tmp, data, sizeof(tmp));
argc = ast_separate_app_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc == 2) {
if (ast_parseoptions(vm_app_options, &flags, opts, argv[1])) {
if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
LOCAL_USER_REMOVE(u);
return -1;
}

@ -317,7 +317,7 @@ static struct agent_pvt *add_agent(char *agent, int pending)
args = ast_strdupa(agent);
// Extract username (agt), password and name from agent (args).
if ((argc = ast_separate_app_args(args, ',', argv, sizeof(argv) / sizeof(argv[0])))) {
if ((argc = ast_app_separate_args(args, ',', argv, sizeof(argv) / sizeof(argv[0])))) {
agt = argv[0];
if (argc > 1) {
password = argv[1];

@ -52,7 +52,7 @@ static char *builtin_function_cdr_read(struct ast_channel *chan, char *cmd, char
return NULL;
mydata = ast_strdupa(data);
argc = ast_separate_app_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
/* check for a trailing flags argument */
if (argc > 1) {
@ -77,7 +77,7 @@ static void builtin_function_cdr_write(struct ast_channel *chan, char *cmd, char
return;
mydata = ast_strdupa(data);
argc = ast_separate_app_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
/* check for a trailing flags argument */
if (argc > 1) {

@ -55,7 +55,7 @@ static char *function_db_read(struct ast_channel *chan, char *cmd, char *data, c
}
args = ast_strdupa(data);
argc = ast_separate_app_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
if (argc > 1) {
family = argv[0];
@ -88,7 +88,7 @@ static void function_db_write(struct ast_channel *chan, char *cmd, char *data, c
}
args = ast_strdupa(data);
argc = ast_separate_app_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
if (argc > 1) {
family = argv[0];
@ -134,7 +134,7 @@ static char *function_db_exists(struct ast_channel *chan, char *cmd, char *data,
}
args = ast_strdupa(data);
argc = ast_separate_app_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(args, '/', argv, sizeof(argv) / sizeof(argv[0]));
if (argc > 1) {
family = argv[0];

@ -84,7 +84,7 @@ static char *builtin_function_math(struct ast_channel *chan, char *cmd, char *da
}
args = ast_strdupa(data);
argc = ast_separate_app_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc < 1) {
ast_log(LOG_WARNING, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");

@ -64,7 +64,7 @@ static char *builtin_function_checkmd5(struct ast_channel *chan, char *cmd, char
}
args = ast_strdupa(data);
argc = ast_separate_app_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc < 2) {
ast_log(LOG_WARNING, "Syntax: CHECK_MD5(<digest>,<data>) - missing argument!\n");

@ -73,17 +73,7 @@ struct ast_ivr_menu {
#define AST_IVR_FLAG_AUTORESTART (1 << 0)
struct ast_option {
unsigned int flag;
int arg_index;
};
extern int ast_parseoptions(const struct ast_option *options, struct ast_flags *flags, char **args, char *optstr);
#define AST_DECLARE_OPTIONS(holder,args...) \
static struct ast_option holder[128] = args
#define AST_IVR_DECLARE_MENU(holder,title,flags,foo...) \
#define AST_IVR_DECLARE_MENU(holder, title, flags, foo...) \
static struct ast_ivr_option __options_##holder[] = foo;\
static struct ast_ivr_menu holder = { title, flags, __options_##holder }
@ -204,7 +194,7 @@ int ast_app_group_match_get_count(char *groupmatch, char *category);
*/
#define AST_DECLARE_APP_ARGS(name, arglist) \
struct { \
int argc; \
unsigned int argc; \
char *argv[0]; \
arglist \
} name;
@ -219,7 +209,7 @@ int ast_app_group_match_get_count(char *groupmatch, char *category);
the argc argument counter field.
*/
#define AST_STANDARD_APP_ARGS(args, parse) \
args.argc = ast_separate_app_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
args.argc = ast_app_separate_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
/*!
\brief Separate a string into arguments in an array
@ -235,7 +225,109 @@ int ast_app_group_match_get_count(char *groupmatch, char *category);
\return The number of arguments found, or zero if the function arguments are not valid.
*/
int ast_separate_app_args(char *buf, char delim, char **array, int arraylen);
unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen);
/*!
\brief A structure to hold the description of an application 'option'.
Application 'options' are single-character flags that can be supplied
to the application to affect its behavior; they can also optionally
accept arguments enclosed in parenthesis.
These structures are used by the ast_app_parse_options function, uses
this data to fill in a flags structure (to indicate which options were
supplied) and array of argument pointers (for those options that had
arguments supplied).
*/
struct ast_app_option {
/*! \brief The flag bit that represents this option. */
unsigned int flag;
/*! \brief The index of the entry in the arguments array
that should be used for this option's argument. */
unsigned int arg_index;
};
/*!
\brief Declares an array of options for an application.
\param holder The name of the array to be created
\param options The actual options to be placed into the array
\sa ast_app_parse_options
This macro declares a 'static const' array of \c struct \c ast_option
elements to hold the list of available options for an application.
Each option must be declared using either the AST_APP_OPTION()
or AST_APP_OPTION_ARG() macros.
Example usage:
\code
enum {
OPT_JUMP = (1 << 0),
OPT_BLAH = (1 << 1),
OPT_BLORT = (1 << 2),
} my_app_option_flags;
enum {
OPT_ARG_BLAH = 0,
OPT_ARG_BLORT,
!! this entry tells how many possible arguments there are,
and must be the last entry in the list
OPT_ARG_ARRAY_SIZE,
} my_app_option_args;
AST_APP_OPTIONS(my_app_options, {
AST_APP_OPTION('j', OPT_JUMP),
AST_APP_OPTION_ARG('b', OPT_BLAH, OPT_ARG_BLAH),
AST_APP_OPTION_BLORT('B', OPT_BLORT, OPT_ARG_BLORT),
});
static int my_app_exec(struct ast_channel *chan, void *data)
{
char *options;
struct ast_flags opts = { 0, };
char *opt_args[OPT_ARG_ARRAY_SIZE];
... do any argument parsing here ...
if (ast_parseoptions(my_app_options, &opts, opt_args, options)) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
\endcode
*/
#define AST_APP_OPTIONS(holder, options...) \
static const struct ast_app_option holder[128] = options
/*!
\brief Declares an application option that does not accept an argument.
\param option The single character representing the option
\param flagno The flag index to be set if this option is present
\sa AST_APP_OPTIONS, ast_app_parse_options
*/
#define AST_APP_OPTION(option, flagno) \
[option] = { .flag = flagno }
/*!
\brief Declares an application option that accepts an argument.
\param option The single character representing the option
\param flagno The flag index to be set if this option is present
\param argno The index into the argument array where the argument should
be placed
\sa AST_APP_OPTIONS, ast_app_parse_options
*/
#define AST_APP_OPTION_ARG(option, flagno, argno) \
[option] = { .flag = flagno, .arg_index = argno }
/*!
\brief Parses a string containing application options and sets flags/arguments.
\param options The array of possible options declared with AST_APP_OPTIONS
\param flags The flag structure to have option flags set
\param args The array of argument pointers to hold arguments found
\param optstr The string containing the options to be parsed
\return zero for success, non-zero if an error occurs
\sa AST_APP_OPTIONS
*/
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr);
/*! Present a dialtone and collect a certain length extension. Returns 1 on valid extension entered, -1 on hangup, or 0 on invalid extension. Note that if 'collect' holds digits already, new digits will be appended, so be sure it's initialized properly */
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout);

35
pbx.c

@ -86,17 +86,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define BACKGROUND_MATCHEXTEN (1 << 2)
#define BACKGROUND_PLAYBACK (1 << 3)
AST_DECLARE_OPTIONS(background_opts,{
['s'] = { BACKGROUND_SKIP },
['n'] = { BACKGROUND_NOANSWER },
['m'] = { BACKGROUND_MATCHEXTEN },
['p'] = { BACKGROUND_PLAYBACK },
AST_APP_OPTIONS(background_opts, {
AST_APP_OPTION('s', BACKGROUND_SKIP),
AST_APP_OPTION('n', BACKGROUND_NOANSWER),
AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
});
#define WAITEXTEN_MOH (1 << 0)
AST_DECLARE_OPTIONS(waitexten_opts,{
['m'] = { WAITEXTEN_MOH, 1 },
AST_APP_OPTIONS(waitexten_opts, {
AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),
});
struct ast_context;
@ -5616,13 +5616,13 @@ static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
char *args;
char *argv[2];
char *options = NULL;
char *mohclass = NULL;
char *timeout = NULL;
struct ast_flags flags = {0};
char *opts[1] = { NULL };
args = ast_strdupa(data);
if ((argc = ast_separate_app_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
if (argc > 0) {
timeout = argv[0];
if (argc > 1)
@ -5630,16 +5630,11 @@ static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
}
}
if (options) {
char *opts[1];
ast_parseoptions(waitexten_opts, &flags, opts, options);
if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
mohclass = opts[0];
}
}
if (options)
ast_app_parse_options(waitexten_opts, &flags, opts, options);
if (ast_test_flag(&flags, WAITEXTEN_MOH))
ast_moh_start(chan, mohclass);
ast_moh_start(chan, opts[0]);
/* Wait for "n" seconds */
if (timeout && atof((char *)timeout))
@ -5685,7 +5680,7 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
parse = ast_strdupa(data);
if ((argc = ast_separate_app_args(parse, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
if ((argc = ast_app_separate_args(parse, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
switch (argc) {
case 4:
context = argv[3];
@ -5714,7 +5709,7 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
else if (!strcasecmp(options, "noanswer"))
flags.flags = BACKGROUND_NOANSWER;
else
ast_parseoptions(background_opts, &flags, NULL, options);
ast_app_parse_options(background_opts, &flags, NULL, options);
}
/* Answer if need be */
@ -5948,7 +5943,7 @@ int pbx_builtin_setvar(struct ast_channel *chan, void *data)
}
mydata = ast_strdupa(data);
argc = ast_separate_app_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
/* check for a trailing flags argument */
if ((argc > 1) && !strchr(argv[argc-1], '=')) {

Loading…
Cancel
Save