source:
freewrt/package/asterisk/patches/asterisk-1.2.0-app_mysql.patch@
428f140
| Last change on this file since 428f140 was 475ad56, checked in by , 20 years ago | |
|---|---|
|
|
| File size: 12.1 KB | |
-
apps/app_sql_mysql.c
diff -ruN asterisk-1.2.0-old/apps/app_sql_mysql.c asterisk-1.2.0-new/apps/app_sql_mysql.c
old new 1 /* 2 * Asterisk -- A telephony toolkit for Linux. 3 * 4 * Connect to MySQL 5 * 6 * Copyright (C) 2004, Constantine Filin and Christos Ricudis 7 * 8 * Christos Ricudis <ricudis@itc.auth.gr> 9 * Constantine Filin <cf@intermedia.net> 10 * 11 * This program is free software, distributed under the terms of 12 * the GNU General Public License 13 */ 14 15 #include <stdlib.h> 16 #include <unistd.h> 17 #include <string.h> 18 #include <stdlib.h> 19 #include <sys/types.h> 20 #include <stdio.h> 21 #include <unistd.h> 22 23 #include <mysql.h> 24 25 #include <asterisk/file.h> 26 #include <asterisk/logger.h> 27 #include <asterisk/channel.h> 28 #include <asterisk/pbx.h> 29 #include <asterisk/module.h> 30 #include <asterisk/linkedlists.h> 31 #include <asterisk/chanvars.h> 32 #include <asterisk/lock.h> 33 34 #define EXTRA_LOG 0 35 36 static char *tdesc = "Simple Mysql Interface"; 37 38 static char *app = "MYSQL"; 39 40 static char *synopsis = "Do several mySQLy things"; 41 42 static char *descrip = 43 "MYSQL(): Do several mySQLy things\n" 44 "Syntax:\n" 45 " MYSQL(Connect connid dhhost dbuser dbpass dbname)\n" 46 " Connects to a database. Arguments contain standard MySQL parameters\n" 47 " passed to function mysql_real_connect. Connection identifer returned\n" 48 " in ${var}\n" 49 " MYSQL(Query resultid ${connid} query-string)\n" 50 " Executes standard MySQL query contained in query-string using established\n" 51 " connection identified by ${connection_identifier}. Result of query is\n" 52 " is stored in ${var}.\n" 53 " MYSQL(Fetch fetchid ${resultid} var1 var2 ... varN)\n" 54 " Fetches a single row from a result set contained in ${result_identifier}.\n" 55 " Assigns returned fields to ${var1} ... ${varn}. ${fetchid} is set TRUE\n" 56 " if additional rows exist in result set.\n" 57 " MYSQL(Clear ${resultid})\n" 58 " Frees memory and datastructures associated with result set.\n" 59 " MYSQL(Disconnect ${connid})\n" 60 " Disconnects from named connection to MySQL.\n" 61 " On exit, always returns 0. Sets MYSQL_STATUS to 0 on success and -1 on error.\n"; 62 63 /* 64 EXAMPLES OF USE : 65 66 exten => s,2,MYSQL(Connect connid localhost asterisk mypass credit) 67 exten => s,3,MYSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM}) 68 exten => s,4,MYSQL(Fetch fetchid ${resultid} datavar1 datavar2) 69 exten => s,5,GotoIf(${fetchid}?6:8) 70 exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.") 71 exten => s,7,Goto(s,4) 72 exten => s,8,MYSQL(Clear ${resultid}) 73 exten => s,9,MYSQL(Disconnect ${connid}) 74 */ 75 76 STANDARD_LOCAL_USER; 77 LOCAL_USER_DECL; 78 79 AST_MUTEX_DEFINE_STATIC(_mysql_mutex); 80 81 #define AST_MYSQL_ID_DUMMY 0 82 #define AST_MYSQL_ID_CONNID 1 83 #define AST_MYSQL_ID_RESID 2 84 #define AST_MYSQL_ID_FETCHID 3 85 86 struct ast_MYSQL_id { 87 int identifier_type; /* 0=dummy, 1=connid, 2=resultid */ 88 int identifier; 89 void *data; 90 AST_LIST_ENTRY(ast_MYSQL_id) entries; 91 } *ast_MYSQL_id; 92 93 AST_LIST_HEAD(MYSQLidshead,ast_MYSQL_id) _mysql_ids_head; 94 95 /* helpful procs */ 96 static void *find_identifier(int identifier,int identifier_type) { 97 struct MYSQLidshead *headp; 98 struct ast_MYSQL_id *i; 99 void *res=NULL; 100 int found=0; 101 102 headp=&_mysql_ids_head; 103 104 if (AST_LIST_LOCK(headp)) { 105 ast_log(LOG_WARNING,"Unable to lock identifiers list\n"); 106 } else { 107 AST_LIST_TRAVERSE(headp,i,entries) { 108 if ((i->identifier==identifier) && (i->identifier_type==identifier_type)) { 109 found=1; 110 res=i->data; 111 break; 112 } 113 } 114 if (!found) { 115 ast_log(LOG_WARNING,"Identifier %d, identifier_type %d not found in identifier list\n",identifier,identifier_type); 116 } 117 AST_LIST_UNLOCK(headp); 118 } 119 120 return res; 121 } 122 123 static int add_identifier(int identifier_type,void *data) { 124 struct ast_MYSQL_id *i,*j; 125 struct MYSQLidshead *headp; 126 int maxidentifier=0; 127 128 headp=&_mysql_ids_head; 129 i=NULL; 130 j=NULL; 131 132 if (AST_LIST_LOCK(headp)) { 133 ast_log(LOG_WARNING,"Unable to lock identifiers list\n"); 134 return(-1); 135 } else { 136 i=malloc(sizeof(struct ast_MYSQL_id)); 137 AST_LIST_TRAVERSE(headp,j,entries) { 138 if (j->identifier>maxidentifier) { 139 maxidentifier=j->identifier; 140 } 141 } 142 i->identifier=maxidentifier+1; 143 i->identifier_type=identifier_type; 144 i->data=data; 145 AST_LIST_INSERT_HEAD(headp,i,entries); 146 AST_LIST_UNLOCK(headp); 147 } 148 return i->identifier; 149 } 150 151 static int del_identifier(int identifier,int identifier_type) { 152 struct ast_MYSQL_id *i; 153 struct MYSQLidshead *headp; 154 int found=0; 155 156 headp=&_mysql_ids_head; 157 158 if (AST_LIST_LOCK(headp)) { 159 ast_log(LOG_WARNING,"Unable to lock identifiers list\n"); 160 } else { 161 AST_LIST_TRAVERSE(headp,i,entries) { 162 if ((i->identifier==identifier) && 163 (i->identifier_type==identifier_type)) { 164 AST_LIST_REMOVE(headp,i,entries); 165 free(i); 166 found=1; 167 break; 168 } 169 } 170 AST_LIST_UNLOCK(headp); 171 } 172 173 if (found==0) { 174 ast_log(LOG_WARNING,"Could not find identifier %d, identifier_type %d in list to delete\n",identifier,identifier_type); 175 return(-1); 176 } else { 177 return(0); 178 } 179 } 180 181 static int set_asterisk_int(struct ast_channel *chan, char *varname, int id) { 182 if( id>=0 ) { 183 char s[100] = ""; 184 snprintf(s, sizeof(s)-1, "%d", id); 185 #if EXTRA_LOG 186 ast_log(LOG_WARNING,"MYSQL: setting var '%s' to value '%s'\n",varname,s); 187 #endif 188 pbx_builtin_setvar_helper(chan,varname,s); 189 } 190 return id; 191 } 192 193 static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data) { 194 return set_asterisk_int(chan,varname,add_identifier(identifier_type,data)); 195 } 196 197 static int safe_scan_int( char** data, char* delim, int def ) { 198 char* end; 199 int res = def; 200 char* s = strsep(data,delim); 201 if( s ) { 202 res = strtol(s,&end,10); 203 if (*end) res = def; /* not an integer */ 204 } 205 return res; 206 } 207 208 /* MYSQL operations */ 209 static int aMYSQL_connect(struct ast_channel *chan, char *data) { 210 211 MYSQL *mysql; 212 213 char *connid_var; 214 char *dbhost; 215 char *dbuser; 216 char *dbpass; 217 char *dbname; 218 219 strsep(&data," "); // eat the first token, we already know it :P 220 221 connid_var=strsep(&data," "); 222 dbhost=strsep(&data," "); 223 dbuser=strsep(&data," "); 224 dbpass=strsep(&data," "); 225 dbname=strsep(&data,"\n"); 226 227 if( connid_var && dbhost && dbuser && dbpass && dbname ) { 228 mysql = mysql_init(NULL); 229 if (mysql) { 230 if (mysql_real_connect(mysql,dbhost,dbuser,dbpass,dbname,0,NULL,0)) { 231 add_identifier_and_set_asterisk_int(chan,connid_var,AST_MYSQL_ID_CONNID,mysql); 232 return 0; 233 } 234 else { 235 ast_log(LOG_WARNING,"mysql_real_connect(mysql,%s,%s,dbpass,%s,...) failed\n",dbhost,dbuser,dbname); 236 } 237 } 238 else { 239 ast_log(LOG_WARNING,"myslq_init returned NULL\n"); 240 } 241 } 242 else { 243 ast_log(LOG_WARNING,"MYSQL(connect is missing some arguments\n"); 244 } 245 246 return -1; 247 } 248 249 static int aMYSQL_query(struct ast_channel *chan, char *data) { 250 251 MYSQL *mysql; 252 MYSQL_RES *mysqlres; 253 254 char *resultid_var; 255 int connid; 256 char *querystring; 257 258 strsep(&data," "); // eat the first token, we already know it :P 259 260 resultid_var = strsep(&data," "); 261 connid = safe_scan_int(&data," ",-1); 262 querystring = strsep(&data,"\n"); 263 264 if (resultid_var && (connid>=0) && querystring) { 265 if ((mysql=find_identifier(connid,AST_MYSQL_ID_CONNID))!=NULL) { 266 mysql_query(mysql,querystring); 267 if ((mysqlres=mysql_use_result(mysql))!=NULL) { 268 add_identifier_and_set_asterisk_int(chan,resultid_var,AST_MYSQL_ID_RESID,mysqlres); 269 return 0; 270 } 271 else if( mysql_field_count(mysql)==0 ) { 272 return 0; // See http://dev.mysql.com/doc/mysql/en/mysql_field_count.html 273 } 274 else { 275 ast_log(LOG_WARNING,"aMYSQL_query: mysql_store_result() failed on query %s\n",querystring); 276 } 277 } 278 else { 279 ast_log(LOG_WARNING,"aMYSQL_query: Invalid connection identifier %d passed in aMYSQL_query\n",connid); 280 } 281 } 282 else { 283 ast_log(LOG_WARNING,"aMYSQL_query: missing some arguments\n"); 284 } 285 286 return -1; 287 } 288 289 290 static int aMYSQL_fetch(struct ast_channel *chan, char *data) { 291 292 MYSQL_RES *mysqlres; 293 MYSQL_ROW mysqlrow; 294 295 char *fetchid_var,*s5,*s6; 296 int resultid,numFields,j; 297 298 strsep(&data," "); // eat the first token, we already know it :P 299 300 fetchid_var = strsep(&data," "); 301 resultid = safe_scan_int(&data," ",-1); 302 303 if (fetchid_var && (resultid>=0) ) { 304 if ((mysqlres=find_identifier(resultid,AST_MYSQL_ID_RESID))!=NULL) { 305 /* Grab the next row */ 306 if ((mysqlrow=mysql_fetch_row(mysqlres))!=NULL) { 307 numFields=mysql_num_fields(mysqlres); 308 for (j=0;j<numFields;j++) { 309 s5=strsep(&data," "); 310 if (s5==NULL) { 311 ast_log(LOG_WARNING,"ast_MYSQL_fetch: More fields (%d) than variables (%d)\n",numFields,j); 312 break; 313 } 314 s6=mysqlrow[j]; 315 pbx_builtin_setvar_helper(chan,s5, s6 ? s6 : "NULL"); 316 } 317 #ifdef EXTRA_LOG 318 ast_log(LOG_WARNING,"ast_MYSQL_fetch: numFields=%d\n",numFields); 319 #endif 320 set_asterisk_int(chan,fetchid_var,1); // try more rows 321 } else { 322 #if EXTRA_LOG 323 ast_log(LOG_WARNING,"ast_MYSQL_fetch : EOF\n"); 324 #endif 325 set_asterisk_int(chan,fetchid_var,0); // no more rows 326 } 327 return 0; 328 } 329 else { 330 ast_log(LOG_WARNING,"aMYSQL_fetch: Invalid result identifier %d passed\n",resultid); 331 } 332 } 333 else { 334 ast_log(LOG_WARNING,"aMYSQL_fetch: missing some arguments\n"); 335 } 336 337 return -1; 338 } 339 340 static int aMYSQL_clear(struct ast_channel *chan, char *data) { 341 342 MYSQL_RES *mysqlres; 343 344 int id; 345 strsep(&data," "); // eat the first token, we already know it :P 346 id = safe_scan_int(&data," \n",-1); 347 if ((mysqlres=find_identifier(id,AST_MYSQL_ID_RESID))==NULL) { 348 ast_log(LOG_WARNING,"Invalid result identifier %d passed in aMYSQL_clear\n",id); 349 } else { 350 mysql_free_result(mysqlres); 351 del_identifier(id,AST_MYSQL_ID_RESID); 352 } 353 354 return 0; 355 } 356 357 static int aMYSQL_disconnect(struct ast_channel *chan, char *data) { 358 359 MYSQL *mysql; 360 int id; 361 strsep(&data," "); // eat the first token, we already know it :P 362 363 id = safe_scan_int(&data," \n",-1); 364 if ((mysql=find_identifier(id,AST_MYSQL_ID_CONNID))==NULL) { 365 ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aMYSQL_disconnect\n",id); 366 } else { 367 mysql_close(mysql); 368 del_identifier(id,AST_MYSQL_ID_CONNID); 369 } 370 371 return 0; 372 } 373 374 static int MYSQL_exec(struct ast_channel *chan, void *data) 375 { 376 struct localuser *u; 377 int result; 378 char sresult[10]; 379 380 #if EXTRA_LOG 381 fprintf(stderr,"MYSQL_exec: data=%s\n",(char*)data); 382 #endif 383 384 if (!data) { 385 ast_log(LOG_WARNING, "APP_MYSQL requires an argument (see manual)\n"); 386 return -1; 387 } 388 389 LOCAL_USER_ADD(u); 390 result=0; 391 392 ast_mutex_lock(&_mysql_mutex); 393 394 if (strncasecmp("connect",data,strlen("connect"))==0) { 395 result=aMYSQL_connect(chan,ast_strdupa(data)); 396 } else if (strncasecmp("query",data,strlen("query"))==0) { 397 result=aMYSQL_query(chan,ast_strdupa(data)); 398 } else if (strncasecmp("fetch",data,strlen("fetch"))==0) { 399 result=aMYSQL_fetch(chan,ast_strdupa(data)); 400 } else if (strncasecmp("clear",data,strlen("clear"))==0) { 401 result=aMYSQL_clear(chan,ast_strdupa(data)); 402 } else if (strncasecmp("disconnect",data,strlen("disconnect"))==0) { 403 result=aMYSQL_disconnect(chan,ast_strdupa(data)); 404 } else { 405 ast_log(LOG_WARNING, "Unknown argument to MYSQL application : %s\n",(char *)data); 406 result=-1; 407 } 408 409 ast_mutex_unlock(&_mysql_mutex); 410 411 LOCAL_USER_REMOVE(u); 412 snprintf(sresult, sizeof(sresult), "%d", result); 413 pbx_builtin_setvar_helper(chan, "MYSQL_STATUS", sresult); 414 return 0; 415 } 416 417 int unload_module(void) 418 { 419 STANDARD_HANGUP_LOCALUSERS; 420 return ast_unregister_application(app); 421 } 422 423 int load_module(void) 424 { 425 struct MYSQLidshead *headp = &_mysql_ids_head; 426 AST_LIST_HEAD_INIT(headp); 427 return ast_register_application(app, MYSQL_exec, synopsis, descrip); 428 } 429 430 char *description(void) 431 { 432 return tdesc; 433 } 434 435 int usecount(void) 436 { 437 int res; 438 STANDARD_USECOUNT(res); 439 return res; 440 } 441 442 char *key() 443 { 444 return ASTERISK_GPL_KEY; 445 }
Note:
See TracBrowser
for help on using the repository browser.
