Asterisk - The Open Source Telephony Project  18.5.0
app_mysql.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004, Constantine Filin and Christos Ricudis
5  *
6  * Christos Ricudis <[email protected]>
7  * Constantine Filin <[email protected]>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*!
21  * \file
22  * \brief MYSQL dialplan application
23  * \ingroup applications
24  */
25 
26 /*! \li \ref app_mysql.c uses the configuration file \ref app_mysql.conf
27  * \addtogroup configuration_file Configuration Files
28  */
29 
30 /*!
31  * \page app_mysql.conf app_mysql.conf
32  * \verbinclude app_mysql.conf.sample
33  */
34 
35 /*** MODULEINFO
36  <depend>mysqlclient</depend>
37  <defaultenabled>no</defaultenabled>
38  <support_level>deprecated</support_level>
39  <replacement>func_odbc</replacement>
40  ***/
41 
42 #include "asterisk.h"
43 
44 #include <mysql/mysql.h>
45 
46 #include "asterisk/file.h"
47 #include "asterisk/logger.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/module.h"
51 #include "asterisk/linkedlists.h"
52 #include "asterisk/chanvars.h"
53 #include "asterisk/lock.h"
54 #include "asterisk/options.h"
55 #include "asterisk/app.h"
56 #include "asterisk/config.h"
57 
58 #define EXTRA_LOG 0
59 
61 
62 static const char app[] = "MYSQL";
63 
64 static const char synopsis[] = "Do several mySQLy things";
65 
66 static const char descrip[] =
67 "MYSQL(): Do several mySQLy things\n"
68 "Syntax:\n"
69 " MYSQL(Set timeout <num>)\n"
70 " Set the connection timeout, in seconds.\n"
71 " MYSQL(Connect connid dhhost[:dbport] dbuser dbpass dbname [dbcharset])\n"
72 " Connects to a database. Arguments contain standard MySQL parameters\n"
73 " passed to function mysql_real_connect. Optional parameter dbcharset\n"
74 " defaults to 'latin1'. Connection identifer returned in ${connid}\n"
75 " MYSQL(Query resultid ${connid} query-string)\n"
76 " Executes standard MySQL query contained in query-string using established\n"
77 " connection identified by ${connid}. Result of query is stored in ${resultid}.\n"
78 " MYSQL(Nextresult resultid ${connid}\n"
79 " If last query returned more than one result set, it stores the next\n"
80 " result set in ${resultid}. It's useful with stored procedures\n"
81 " MYSQL(Fetch fetchid ${resultid} var1 var2 ... varN)\n"
82 " Fetches a single row from a result set contained in ${result_identifier}.\n"
83 " Assigns returned fields to ${var1} ... ${varn}. ${fetchid} is set TRUE\n"
84 " if additional rows exist in result set.\n"
85 " MYSQL(Clear ${resultid})\n"
86 " Frees memory and datastructures associated with result set.\n"
87 " MYSQL(Disconnect ${connid})\n"
88 " Disconnects from named connection to MySQL.\n"
89 " On exit, always returns 0. Sets MYSQL_STATUS to 0 on success and -1 on error.\n";
90 
91 /*
92 EXAMPLES OF USE :
93 
94 exten => s,2,MYSQL(Connect connid localhost asterisk mypass credit utf8)
95 exten => s,3,MYSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
96 exten => s,4,MYSQL(Fetch fetchid ${resultid} datavar1 datavar2)
97 exten => s,5,GotoIf(${fetchid}?6:8)
98 exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
99 exten => s,7,Goto(s,4)
100 exten => s,8,MYSQL(Clear ${resultid})
101 exten => s,9,MYSQL(Disconnect ${connid})
102 */
103 
105 
106 #define MYSQL_CONFIG "app_mysql.conf"
107 #define MYSQL_CONFIG_OLD "mysql.conf"
108 #define AST_MYSQL_ID_DUMMY 0
109 #define AST_MYSQL_ID_CONNID 1
110 #define AST_MYSQL_ID_RESID 2
111 #define AST_MYSQL_ID_FETCHID 3
112 
113 static int autoclear = 0;
114 
115 static void mysql_ds_destroy(void *data);
116 static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan);
117 
118 static const struct ast_datastore_info mysql_ds_info = {
119  .type = "APP_ADDON_SQL_MYSQL",
120  .destroy = mysql_ds_destroy,
121  .chan_fixup = mysql_ds_fixup,
122 };
123 
124 struct ast_MYSQL_id {
126  int identifier_type; /* 0=dummy, 1=connid, 2=resultid */
128  void *data;
130 } *ast_MYSQL_id;
131 
133 
134 static void mysql_ds_destroy(void *data)
135 {
136  /* Destroy any IDs owned by the channel */
137  struct ast_MYSQL_id *i;
139  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
140  } else {
142  if (i->owner == data) {
145  /* Drop connection */
146  mysql_close(i->data);
147  } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
148  /* Drop result */
149  mysql_free_result(i->data);
150  }
151  ast_free(i);
152  }
153  }
156  }
157 }
158 
159 static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
160 {
161  /* Destroy any IDs owned by the channel */
162  struct ast_MYSQL_id *i;
164  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
165  } else {
167  if (i->owner == data) {
170  /* Drop connection */
171  mysql_close(i->data);
172  } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
173  /* Drop result */
174  mysql_free_result(i->data);
175  }
176  ast_free(i);
177  }
178  }
181  }
182 }
183 
184 /* helpful procs */
186 {
187  struct MYSQLidshead *headp = &_mysql_ids_head;
188  struct ast_MYSQL_id *i;
189  void *res=NULL;
190  int found=0;
191 
192  if (AST_LIST_LOCK(headp)) {
193  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
194  } else {
195  AST_LIST_TRAVERSE(headp, i, entries) {
196  if ((i->identifier == identifier) && (i->identifier_type == identifier_type)) {
197  found = 1;
198  res = i->data;
199  break;
200  }
201  }
202  if (!found) {
203  ast_log(LOG_WARNING, "Identifier %d, identifier_type %d not found in identifier list\n", identifier, identifier_type);
204  }
205  AST_LIST_UNLOCK(headp);
206  }
207 
208  return res;
209 }
210 
211 static int add_identifier(struct ast_channel *chan, int identifier_type, void *data)
212 {
213  struct ast_MYSQL_id *i = NULL, *j = NULL;
214  struct MYSQLidshead *headp = &_mysql_ids_head;
215  int maxidentifier = 0;
216 
217  if (AST_LIST_LOCK(headp)) {
218  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
219  return -1;
220  } else {
221  i = ast_malloc(sizeof(*i));
222  AST_LIST_TRAVERSE(headp, j, entries) {
223  if (j->identifier > maxidentifier) {
224  maxidentifier = j->identifier;
225  }
226  }
227  i->identifier = maxidentifier + 1;
229  i->data = data;
230  i->owner = chan;
231  AST_LIST_INSERT_HEAD(headp, i, entries);
232  AST_LIST_UNLOCK(headp);
233  }
234  return i->identifier;
235 }
236 
238 {
239  struct ast_MYSQL_id *i;
240  struct MYSQLidshead *headp = &_mysql_ids_head;
241  int found = 0;
242 
243  if (AST_LIST_LOCK(headp)) {
244  ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
245  } else {
246  AST_LIST_TRAVERSE(headp, i, entries) {
247  if ((i->identifier == identifier) &&
248  (i->identifier_type == identifier_type)) {
249  AST_LIST_REMOVE(headp, i, entries);
250  ast_free(i);
251  found = 1;
252  break;
253  }
254  }
255  AST_LIST_UNLOCK(headp);
256  }
257 
258  if (found == 0) {
259  ast_log(LOG_WARNING, "Could not find identifier %d, identifier_type %d in list to delete\n", identifier, identifier_type);
260  return -1;
261  } else {
262  return 0;
263  }
264 }
265 
266 static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
267 {
268  if (id >= 0) {
269  char s[12] = "";
270  snprintf(s, sizeof(s), "%d", id);
271  ast_debug(5, "MYSQL: setting var '%s' to value '%s'\n", varname, s);
272  pbx_builtin_setvar_helper(chan, varname, s);
273  }
274  return id;
275 }
276 
277 static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
278 {
279  return set_asterisk_int(chan, varname, add_identifier(chan, identifier_type, data));
280 }
281 
282 static int safe_scan_int(char **data, char *delim, int def)
283 {
284  char *end;
285  int res = def;
286  char *s = strsep(data, delim);
287  if (s) {
288  res = strtol(s, &end, 10);
289  if (*end)
290  res = def; /* not an integer */
291  }
292  return res;
293 }
294 
295 static int aMYSQL_set(struct ast_channel *chan, const char *data)
296 {
297  char *var, *tmp, *parse;
299  AST_APP_ARG(set);
300  AST_APP_ARG(variable);
302  );
303 
304  parse = ast_strdupa(data);
305  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
306 
307  if (args.argc == 3) {
308  var = ast_alloca(6 + strlen(args.variable) + 1);
309  sprintf(var, "MYSQL_%s", args.variable);
310 
311  /* Make the parameter case-insensitive */
312  for (tmp = var + 6; *tmp; tmp++)
313  *tmp = toupper(*tmp);
314 
315  pbx_builtin_setvar_helper(chan, var, args.value);
316  }
317  return 0;
318 }
319 
320 /* MYSQL operations */
321 static int aMYSQL_connect(struct ast_channel *chan, const char *data)
322 {
324  AST_APP_ARG(connect);
325  AST_APP_ARG(connid);
331  );
332  MYSQL *mysql;
333  int timeout;
334  const char *ctimeout;
335  unsigned int port = 0;
336  char *port_str;
337  char *parse = ast_strdupa(data);
338 
339  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
340 
341  if (args.argc < 6) {
342  ast_log(LOG_WARNING, "MYSQL_connect is missing some arguments\n");
343  return -1;
344  }
345 
346  if (!(mysql = mysql_init(NULL))) {
347  ast_log(LOG_WARNING, "mysql_init returned NULL\n");
348  return -1;
349  }
350 
351  ctimeout = pbx_builtin_getvar_helper(chan, "MYSQL_TIMEOUT");
352  if (ctimeout && sscanf(ctimeout, "%30d", &timeout) == 1) {
353  mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout);
354  }
355  if(args.dbcharset && strlen(args.dbcharset) > 2){
356  char set_names[255];
357  char statement[512];
358  snprintf(set_names, sizeof(set_names), "SET NAMES %s", args.dbcharset);
359  mysql_real_escape_string(mysql, statement, set_names, sizeof(set_names));
360  mysql_options(mysql, MYSQL_INIT_COMMAND, set_names);
361  mysql_options(mysql, MYSQL_SET_CHARSET_NAME, args.dbcharset);
362  }
363 
364  if ((port_str = strchr(args.dbhost, ':'))) {
365  *port_str++ = '\0';
366  if (sscanf(port_str, "%u", &port) != 1) {
367  ast_log(LOG_WARNING, "Invalid port: '%s'\n", port_str);
368  port = 0;
369  }
370  }
371 
372  if (!mysql_real_connect(mysql, args.dbhost, args.dbuser, args.dbpass, args.dbname, port, NULL,
373 #ifdef CLIENT_MULTI_STATEMENTS
374  CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS
375 #elif defined(CLIENT_MULTI_QUERIES)
376  CLIENT_MULTI_QUERIES
377 #else
378  0
379 #endif
380  )) {
381  ast_log(LOG_WARNING, "mysql_real_connect(mysql,%s,%s,dbpass,%s,...) failed(%d): %s\n",
382  args.dbhost, args.dbuser, args.dbname, mysql_errno(mysql), mysql_error(mysql));
383  return -1;
384  }
385 
387  return 0;
388 }
389 
390 static int aMYSQL_query(struct ast_channel *chan, const char *data)
391 {
393  AST_APP_ARG(query);
394  AST_APP_ARG(resultid);
395  AST_APP_ARG(connid);
396  AST_APP_ARG(sql);
397  );
398  MYSQL *mysql;
399  MYSQL_RES *mysqlres;
400  int connid;
401  int mysql_query_res;
402  char *parse = ast_strdupa(data);
403 
404  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
405 
406  if (args.argc != 4 || (connid = atoi(args.connid)) == 0) {
407  ast_log(LOG_WARNING, "missing some arguments\n");
408  return -1;
409  }
410 
411  if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
412  ast_log(LOG_WARNING, "Invalid connection identifier %s passed in aMYSQL_query\n", args.connid);
413  return -1;
414  }
415 
416  if ((mysql_query_res = mysql_query(mysql, args.sql)) != 0) {
417  ast_log(LOG_WARNING, "aMYSQL_query: mysql_query failed. Error: %s\n", mysql_error(mysql));
418  return -1;
419  }
420 
421  if ((mysqlres = mysql_store_result(mysql))) {
423  return 0;
424  } else if (!mysql_field_count(mysql)) {
425  return 0;
426  } else
427  ast_log(LOG_WARNING, "mysql_store_result() failed on query %s\n", args.sql);
428 
429  return -1;
430 }
431 
432 static int aMYSQL_nextresult(struct ast_channel *chan, const char *data)
433 {
434  MYSQL *mysql;
435  MYSQL_RES *mysqlres;
437  AST_APP_ARG(nextresult);
438  AST_APP_ARG(resultid);
439  AST_APP_ARG(connid);
440  );
441  int connid = -1;
442  char *parse = ast_strdupa(data);
443 
444  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
445  sscanf(args.connid, "%30d", &connid);
446 
447  if (args.argc != 3 || connid <= 0) {
448  ast_log(LOG_WARNING, "missing some arguments\n");
449  return -1;
450  }
451 
452  if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
453  ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_query\n", connid);
454  return -1;
455  }
456 
457  if (mysql_more_results(mysql)) {
458  mysql_next_result(mysql);
459  if ((mysqlres = mysql_store_result(mysql))) {
461  return 0;
462  } else if (!mysql_field_count(mysql)) {
463  return 0;
464  } else
465  ast_log(LOG_WARNING, "mysql_store_result() failed on storing next_result\n");
466  } else
467  ast_log(LOG_WARNING, "mysql_more_results() result set has no more results\n");
468 
469  return 0;
470 }
471 
472 
473 static int aMYSQL_fetch(struct ast_channel *chan, const char *data)
474 {
475  MYSQL_RES *mysqlres;
476  MYSQL_ROW mysqlrow;
478  AST_APP_ARG(fetch);
479  AST_APP_ARG(resultvar);
480  AST_APP_ARG(fetchid);
481  AST_APP_ARG(vars);
482  );
483  char *s5, *parse;
484  int resultid = -1, numFields, j;
485 
486  parse = ast_strdupa(data);
487  AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
488  sscanf(args.fetchid, "%30d", &resultid);
489 
490  if (args.resultvar && (resultid >= 0) ) {
491  if ((mysqlres = find_identifier(resultid, AST_MYSQL_ID_RESID)) != NULL) {
492  /* Grab the next row */
493  if ((mysqlrow = mysql_fetch_row(mysqlres)) != NULL) {
494  numFields = mysql_num_fields(mysqlres);
495  for (j = 0; j < numFields; j++) {
496  s5 = strsep(&args.vars, " ");
497  if (s5 == NULL) {
498  ast_log(LOG_WARNING, "ast_MYSQL_fetch: More fields (%d) than variables (%d)\n", numFields, j);
499  break;
500  }
501 
502  pbx_builtin_setvar_helper(chan, s5, mysqlrow[j] ? mysqlrow[j] :
503  nullvalue == NULLSTRING ? "NULL" :
504  nullvalue == EMPTYSTRING ? "" :
505  NULL);
506  }
507  ast_debug(5, "ast_MYSQL_fetch: numFields=%d\n", numFields);
508  set_asterisk_int(chan, args.resultvar, 1); /* try more rows */
509  } else {
510  ast_debug(5, "ast_MYSQL_fetch : EOF\n");
511  set_asterisk_int(chan, args.resultvar, 0); /* no more rows */
512  }
513  return 0;
514  } else {
515  set_asterisk_int(chan, args.resultvar, 0);
516  ast_log(LOG_WARNING, "aMYSQL_fetch: Invalid result identifier %d passed\n", resultid);
517  }
518  } else {
519  ast_log(LOG_WARNING, "aMYSQL_fetch: missing some arguments\n");
520  }
521 
522  return -1;
523 }
524 
525 static int aMYSQL_clear(struct ast_channel *chan, const char *data)
526 {
527  MYSQL_RES *mysqlres;
528 
529  int id;
530  char *parse = ast_strdupa(data);
531  strsep(&parse, " "); /* eat the first token, we already know it :P */
532  id = safe_scan_int(&parse, " \n", -1);
533  if ((mysqlres = find_identifier(id, AST_MYSQL_ID_RESID)) == NULL) {
534  ast_log(LOG_WARNING, "Invalid result identifier %d passed in aMYSQL_clear\n", id);
535  } else {
536  mysql_free_result(mysqlres);
538  }
539 
540  return 0;
541 }
542 
543 static int aMYSQL_disconnect(struct ast_channel *chan, const char *data)
544 {
545  MYSQL *mysql;
546  int id;
547  char *parse = ast_strdupa(data);
548  strsep(&parse, " "); /* eat the first token, we already know it :P */
549 
550  id = safe_scan_int(&parse, " \n", -1);
551  if ((mysql = find_identifier(id, AST_MYSQL_ID_CONNID)) == NULL) {
552  ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_disconnect\n", id);
553  } else {
554  mysql_close(mysql);
556  }
557 
558  return 0;
559 }
560 
561 static int MYSQL_exec(struct ast_channel *chan, const char *data)
562 {
563  int result;
564  char sresult[10];
565 
566  ast_debug(5, "MYSQL: data=%s\n", data);
567 
568  if (!data) {
569  ast_log(LOG_WARNING, "MYSQL requires an argument (see manual)\n");
570  return -1;
571  }
572 
573  result = 0;
574 
575  if (autoclear) {
576  struct ast_datastore *mysql_store = NULL;
577 
578  ast_channel_lock(chan);
579  mysql_store = ast_channel_datastore_find(chan, &mysql_ds_info, NULL);
580  if (!mysql_store) {
581  if (!(mysql_store = ast_datastore_alloc(&mysql_ds_info, NULL))) {
582  ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
583  } else {
584  mysql_store->data = chan;
585  ast_channel_datastore_add(chan, mysql_store);
586  }
587  }
588  ast_channel_unlock(chan);
589  }
591 
592  if (strncasecmp("connect", data, strlen("connect")) == 0) {
593  result = aMYSQL_connect(chan, data);
594  } else if (strncasecmp("query", data, strlen("query")) == 0) {
595  result = aMYSQL_query(chan, data);
596  } else if (strncasecmp("nextresult", data, strlen("nextresult")) == 0) {
597  result = aMYSQL_nextresult(chan, data);
598  } else if (strncasecmp("fetch", data, strlen("fetch")) == 0) {
599  result = aMYSQL_fetch(chan, data);
600  } else if (strncasecmp("clear", data, strlen("clear")) == 0) {
601  result = aMYSQL_clear(chan, data);
602  } else if (strncasecmp("disconnect", data, strlen("disconnect")) == 0) {
603  result = aMYSQL_disconnect(chan, data);
604  } else if (strncasecmp("set", data, 3) == 0) {
605  result = aMYSQL_set(chan, data);
606  } else {
607  ast_log(LOG_WARNING, "Unknown argument to MYSQL application : %s\n", data);
608  result = -1;
609  }
610 
612 
613  snprintf(sresult, sizeof(sresult), "%d", result);
614  pbx_builtin_setvar_helper(chan, "MYSQL_STATUS", sresult);
615  return 0;
616 }
617 
618 static int unload_module(void)
619 {
621 }
622 
623 /*!
624  * \brief Load the module
625  *
626  * Module loading including tests for configuration or dependencies.
627  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
628  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
629  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
630  * configuration file or other non-critical problem return
631  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
632  */
633 static int load_module(void)
634 {
635  struct MYSQLidshead *headp = &_mysql_ids_head;
636  struct ast_flags config_flags = { 0 };
637  struct ast_config *cfg = ast_config_load(MYSQL_CONFIG, config_flags);
638  const char *temp;
639 
640  if (!cfg) {
641  /* Backwards compatibility ftw */
642  cfg = ast_config_load(MYSQL_CONFIG_OLD, config_flags);
643  }
644 
645  if (cfg) {
646  if ((temp = ast_variable_retrieve(cfg, "general", "nullvalue"))) {
647  if (!strcasecmp(temp, "nullstring")) {
649  } else if (!strcasecmp(temp, "emptystring")) {
651  } else if (!strcasecmp(temp, "null")) {
653  } else {
654  ast_log(LOG_WARNING, "Illegal value for 'nullvalue': '%s' (must be 'nullstring', 'null', or 'emptystring')\n", temp);
655  }
656  }
657  if ((temp = ast_variable_retrieve(cfg, "general", "autoclear")) && ast_true(temp)) {
658  autoclear = 1;
659  }
660  ast_config_destroy(cfg);
661  }
662 
663  AST_LIST_HEAD_INIT(headp);
665 }
666 
667 AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Simple Mysql Interface");
const char * type
Definition: datastore.h:32
static const char synopsis[]
Definition: app_mysql.c:64
static ast_mutex_t _mysql_mutex
Definition: app_mysql.c:104
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
static int aMYSQL_clear(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:525
static int aMYSQL_set(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:295
static int safe_scan_int(char **data, char *delim, int def)
Definition: app_mysql.c:282
static int aMYSQL_query(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:390
Channel Variables.
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
Definition: app_mysql.c:266
#define MYSQL_CONFIG_OLD
Definition: app_mysql.c:107
int identifier
Definition: app_mysql.c:127
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
static int add_identifier(struct ast_channel *chan, int identifier_type, void *data)
Definition: app_mysql.c:211
#define var
Definition: ast_expr2f.c:614
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Simple Mysql Interface")
Structure for a data store type.
Definition: datastore.h:31
static int load_module(void)
Load the module.
Definition: app_mysql.c:633
static int aMYSQL_connect(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:321
struct MYSQLidshead _mysql_ids_head
static int aMYSQL_nextresult(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:432
#define ast_mutex_lock(a)
Definition: lock.h:187
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
static int autoclear
Definition: app_mysql.c:113
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char * args
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int value
Definition: syslog.c:37
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
static char dbpass[MAX_DB_OPTION_SIZE]
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static void mysql_ds_destroy(void *data)
Definition: app_mysql.c:134
static int MYSQL_exec(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:561
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static struct ast_str * dbcharset
Definition: cdr_mysql.c:77
static int unload_module(void)
Definition: app_mysql.c:618
Configuration File Parser.
static void * find_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:185
static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
Definition: app_mysql.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define AST_MYSQL_ID_CONNID
Definition: app_mysql.c:109
General Asterisk PBX channel definitions.
#define ast_register_application(app, execute, synopsis, description)
Register an application.
Definition: module.h:610
static const char descrip[]
Definition: app_mysql.c:66
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static int aMYSQL_fetch(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:473
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int del_identifier(int identifier, int identifier_type)
Definition: app_mysql.c:237
#define MYSQL_CONFIG
Definition: app_mysql.c:106
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
struct ast_MYSQL_id * ast_MYSQL_id
static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: app_mysql.c:159
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
struct ast_channel * owner
Definition: app_mysql.c:125
enum @0 nullvalue
struct ast_MYSQL_id::@1 entries
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static struct ast_str * dbname
Definition: cdr_mysql.c:77
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_free(a)
Definition: astmm.h:182
void * data
Definition: app_mysql.c:128
Structure used to handle boolean flags.
Definition: utils.h:199
Support for logging to various files, console and syslog Configuration in file logger.conf.
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...
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void * data
Definition: datastore.h:70
char * strsep(char **str, const char *delims)
static int aMYSQL_disconnect(struct ast_channel *chan, const char *data)
Definition: app_mysql.c:543
static struct ast_str * dbuser
Definition: cdr_mysql.c:77
static PGresult * result
Definition: cel_pgsql.c:88
Options provided by main asterisk program.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
enum queue_result id
Definition: app_queue.c:1507
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_MYSQL_ID_RESID
Definition: app_mysql.c:110
int identifier_type
Definition: app_mysql.c:126
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static const char app[]
Definition: app_mysql.c:62
static char dbhost[MAX_DB_OPTION_SIZE]
Asterisk module definitions.
static MYSQL mysql
Definition: cdr_mysql.c:109
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static const struct ast_datastore_info mysql_ds_info
Definition: app_mysql.c:118
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define AST_APP_ARG(name)
Define an application argument.