packages/db_spec.c
#include "spec.h"
#if defined(MSQL)
string sql_escape(string);
mixed *sql_exec(string);
#endif /* MSQL, ... */
#if defined(GDBM)
int dbm_exists(string, string);
mixed dbm_query(string, string);
int dbm_store(string, string, mixed);
int dbm_delete(string, string);
string *dbm_keys(string, string|void);
#endif /* GDBM, ... */
packages/db.h
#ifndef l_db_h
#define l_db_h
#if defined(MSQL)
#include "/usr/local/include/mysql/mysql.h"
static MYSQL *dbh = NULL;
#endif /* MSQL, ... */
#if defined(GDBM)
#include "/usr/local/include/gdbm.h"
int dbm_exists (char * db, char * keystr);
svalue_t *dbm_query (char * db, char * keystr);
int dbm_store (char * db, char * key, svalue_t * val);
int dbm_delete (char * db, char * keystr);
array_t *dbm_keys (char * db, char * pattern);
#endif /* GDBM, ... */
#endif /* l_db_h */
packages/db.c
/* Database package for the MudOS driver
* Designed to allow people to write datbase independent LPC
* Currently supports MYSQL
* created 960124 by George Reese
* No MSQL / George Reese code remains as of 20011101
*/
#include "std.h"
#include "md.h"
#include "../lpc_incl.h"
#include "../mapping.h"
#include "../comm.h"
#include "../file_incl.h"
#include "../file.h"
#include "../object.h"
#include "../eoperators.h"
#include "../backend.h"
#include "db.h"
#include <sys/types.h>
#include "/usr/local/include/pcreposix.h"
#if defined(MSQL) /* other SQL types here? */
#ifdef F_SQL_ESCAPE
void f_sql_escape (void) {
char *s, *e;
s = sp->u.string;
e = (char *)DXALLOC((strlen(s) * 2) + 1, TAG_DB, "f_sql_escape");
mysql_escape_string(e, s, strlen(s));
pop_n_elems(1);
copy_and_push_string(e);
FREE(e);
}
#endif /* F_SQL_ESCAPE */
#ifdef F_SQL_EXEC
void f_sql_exec (void) {
int i, j, f, r;
char *q, *e;
array_t *ret, *data;
MYSQL_ROW row;
MYSQL_RES *sth;
MYSQL_FIELD *field;
q = sp->u.string;
if ((dbh = mysql_init(NULL)) == NULL) {
error("Unable to initialize SQL handle.\n");
}
if (mysql_real_connect(dbh, NULL, "starmud", NULL, "starmud", 0, NULL, 0) == NULL) {
mysql_close(dbh);
error("Unable to connect to SQL database.\n");
}
if (mysql_query(dbh, q) != 0) {
e = new_string(strlen(mysql_error(dbh)), "f_sql_exec");
strcpy(e, mysql_error(dbh));
strcat(e, "\n");
mysql_close(dbh);
error_needs_free(e);
}
if ((sth = mysql_store_result(dbh)) == NULL) {
if (mysql_field_count(dbh) == 0) {
mysql_close(dbh);
pop_n_elems(1);
push_refed_array(&the_null_array);
return;
} else {
e = new_string(strlen(mysql_error(dbh)), "f_sql_exec");
strcpy(e, mysql_error(dbh));
strcat(e, "\n");
mysql_close(dbh);
error_needs_free(e);
}
}
if ((r = mysql_num_rows(sth)) == 0) {
mysql_free_result(sth);
mysql_close(dbh);
pop_n_elems(1);
push_refed_array(&the_null_array);
return;
}
ret = allocate_empty_array(r);
f = mysql_num_fields(sth);
for (i = 0; i < r; i++) {
row = mysql_fetch_row(sth);
data = allocate_empty_array(f);
for (j = 0; j < f; j++) {
data->item[j] = const0u;
field = (row ? mysql_fetch_field_direct(sth, j) : NULL);
if (field != NULL && row[j] != NULL) {
switch (field->type) {
case FIELD_TYPE_TINY:
case FIELD_TYPE_SHORT:
case FIELD_TYPE_LONG:
data->item[j].type = T_NUMBER;
data->item[j].u.number = atoi(row[j]);
break;
case FIELD_TYPE_FLOAT:
case FIELD_TYPE_DOUBLE:
case FIELD_TYPE_DECIMAL:
case FIELD_TYPE_NEWDECIMAL:
data->item[j].type = T_REAL;
data->item[j].u.real = atof(row[j]);
break;
default:
data->item[j].type = T_STRING;
data->item[j].subtype = STRING_MALLOC;
data->item[j].u.string = string_copy(row[j], "f_sql_exec");
break;
}
}
}
ret->item[i].type = T_ARRAY;
ret->item[i].u.arr = data;
}
mysql_free_result(sth);
mysql_close(dbh);
pop_n_elems(1);
push_refed_array(ret);
}
#endif /* F_SQL_EXEC */
#endif /* MYSQL, ... */
#if defined(GDBM) /* Based on Benny Holmgren's code for dbm/lpc interface. */
#ifdef F_DBM_EXISTS
void f_dbm_exists (void) {
int ret;
ret = dbm_exists((sp-1)->u.string, sp->u.string);
pop_n_elems(2);
push_number(ret);
}
#endif
#ifdef F_DBM_QUERY
void f_dbm_query (void) {
svalue_t *ret;
ret = dbm_query((sp-1)->u.string, sp->u.string);
pop_n_elems(2);
if( ret ) {
switch( ret->type ) {
case T_NUMBER:
push_number(ret->u.number);
break;
case T_STRING:
copy_and_push_string(ret->u.string);
break;
case T_REAL:
push_real(ret->u.real);
break;
case T_ARRAY:
push_array(ret->u.arr);
break;
case T_MAPPING:
push_mapping(ret->u.map);
break;
default: fatal("Bogus svalue in dbm_query(), type %d\n", ret->type);
}
free_svalue(ret, "f_dbm_query");
FREE(ret);
} else {
push_undefined();
}
}
#endif
#ifdef F_DBM_STORE
void f_dbm_store (void) {
int ret;
if( !(sp->type & (T_NUMBER|T_STRING|T_REAL|T_ARRAY|T_MAPPING)) )
bad_argument(sp, (T_NUMBER|T_STRING|T_REAL|T_ARRAY|T_MAPPING), 3, F_DBM_STORE);
ret = dbm_store((sp-2)->u.string, (sp-1)->u.string, sp);
pop_n_elems(3);
push_number(ret);
}
#endif
#ifdef F_DBM_DELETE
void f_dbm_delete (void) {
int ret;
ret = dbm_delete((sp-1)->u.string, sp->u.string);
pop_n_elems(2);
push_number(ret);
}
#endif
#ifdef F_DBM_KEYS
void f_dbm_keys (void) {
array_t *ret;
if (st_num_arg == 2) {
ret = dbm_keys((sp-1)->u.string, sp->u.string);
pop_n_elems(2);
} else {
ret = dbm_keys(sp->u.string, (char *)NULL);
pop_n_elems(1);
}
if( ret ) {
push_refed_array(ret);
} else
push_number(0);
}
#endif
int dbm_exists (char * db, char * keystr) {
int ret;
char *file;
datum key;
GDBM_FILE dbf;
if( !(file = check_valid_path(db, current_object, "dbm_exists", 0) ) )
error("Denied read permission for database.\n");
dbf = gdbm_open(file, 0, GDBM_READER, 0660, NULL);
if( !dbf )
return 0;
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
ret = gdbm_exists(dbf, key);
gdbm_close(dbf);
return ret;
}
svalue_t *dbm_query (char * db, char * keystr) {
int ret;
char *file;
datum key, content;
svalue_t *val;
GDBM_FILE dbf;
extern svalue_t const0u;
if( !(file = check_valid_path(db, current_object, "dbm_query", 0) ) )
error("Denied read permission for database.\n");
dbf = gdbm_open(file, 0, GDBM_READER, 0660, NULL);
if( !dbf )
return (svalue_t *)NULL;
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
content = gdbm_fetch(dbf, key);
gdbm_close(dbf);
if( !content.dptr )
return (svalue_t *)NULL;
val = (svalue_t *)DXALLOC(sizeof(svalue_t), TAG_DB, "dbm_query");
*val = const0u;
ret = restore_svalue(content.dptr, val);
free(content.dptr);
switch( ret ) {
case -1:
FREE((char *)val);
error("dbm_query(): Illegal array format.\n");
case -2:
FREE((char *)val);
error("dbm_query(): Illegal mapping format.\n");
default: break;
}
return val;
}
int dbm_store (char * db, char * keystr, svalue_t * val) {
int ret, savesize;
datum key, content;
char *savestr, *tmp, *file;
GDBM_FILE dbf;
extern int save_svalue_depth;
if( !(file = check_valid_path(db, current_object, "dbm_store", 1) ) )
error("Denied write permission for database.\n");
dbf = gdbm_open(file, 0, GDBM_WRCREAT, 0660, NULL);
if( !dbf )
return 0;
save_svalue_depth = 0;
savesize = svalue_save_size(val);
if (save_svalue_depth > MAX_SAVE_SVALUE_DEPTH)
error("Mappings and/or arrays nested too deep for dbm_store()\n",
MAX_SAVE_SVALUE_DEPTH);
savestr = (char *)DXALLOC(savesize, TAG_DB, "dbm_store");
*savestr = '\0';
tmp = savestr;
save_svalue(val, &tmp);
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
content.dptr = savestr;
content.dsize = strlen(savestr) + 1;
ret = gdbm_store(dbf, key, content, GDBM_REPLACE);
gdbm_close(dbf);
FREE(savestr);
return (!ret);
}
int dbm_delete (char * db, char * keystr) {
int ret;
char *file;
datum key;
GDBM_FILE dbf;
if( !(file = check_valid_path(db, current_object, "dbm_delete", 1) ) )
error("Denied write permission for database.\n");
dbf = gdbm_open(file, 0, GDBM_WRITER, 0660, NULL);
if( !dbf )
return 0;
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
ret = gdbm_delete(dbf, key);
gdbm_close(dbf);
return (!ret);
}
array_t *dbm_keys (char * db, char * pattern) {
array_t *ret;
int keycnt;
datum key, nextkey;
char *file;
GDBM_FILE dbf;
regex_t rexp;
extern int eval_cost;
if( !(file = check_valid_path(db, current_object, "dbm_keys", 0) ) )
error("Denied read permission for database.\n");
if( pattern ) {
if( regcomp(&rexp, pattern, REG_EXTENDED|REG_NOSUB) != 0 )
return (array_t *)NULL;
}
dbf = gdbm_open(file, 0, GDBM_READER, 0660, NULL);
if( !dbf )
return (array_t *)NULL;
keycnt = 0;
key = gdbm_firstkey(dbf);
while( key.dptr ) {
nextkey = gdbm_nextkey(dbf, key);
free(key.dptr);
if( !pattern || regexec(&rexp, key.dptr, 0, NULL, 0) == 0 )
keycnt++;
key = nextkey;
}
ret = allocate_empty_array(keycnt);
key = gdbm_firstkey(dbf);
while( key.dptr ) {
nextkey = gdbm_nextkey(dbf, key);
if( !pattern || regexec(&rexp, key.dptr, 0, NULL, 0) == 0 ) {
--keycnt;
ret->item[keycnt].type = T_STRING;
ret->item[keycnt].subtype = STRING_MALLOC; /* should we make it shared? */
ret->item[keycnt].u.string = string_copy(key.dptr, "f_dbm_keys");
}
free(key.dptr);
key = nextkey;
}
gdbm_close(dbf);
if( pattern )
regfree(&rexp);
return ret;
}
#endif /* GDBM, ... */
mv -f driver driver.old
mv: rename driver to driver.old: No such file or directory
gmake[1]: [GNUmakefile:113: driver] Error 1 (ignored)
gcc -D__USE_FIXED_PROTOTYPES__ -O2 obj/grammar.tab.o obj/lex.o obj/main.o obj/rc.o obj/interpret.o obj/simulate.o obj/file.o obj/object.o obj/backend.o obj/array.o obj/mapping.o obj/comm.o obj/ed.o obj/regexp.o obj/buffer.o obj/crc32.o obj/malloc.o obj/mallocwrapper.o obj/class.o obj/efuns_main.o obj/efuns_port.o obj/call_out.o obj/otable.o obj/dumpstat.o obj/stralloc.o obj/hash.o obj/port.o obj/reclaim.o obj/parse.o obj/simul_efun.o obj/sprintf.o obj/program.o obj/compiler.o obj/avltree.o obj/icode.o obj/trees.o obj/generate.o obj/scratchpad.o obj/socket_efuns.o obj/socket_ctrl.o obj/qsort.o obj/eoperators.o obj/socket_err.o obj/md.o obj/disassembler.o obj/uvalarm.o obj/replace_program.o obj/master.o obj/function.o obj/debug.o obj/crypt.o obj/applies_table.o obj/add_action.o obj/eval.o obj/fliconv.o obj/console.o `./dtrace_compile` -o driver packages/packages.a `cat system_libs`
packages/packages.a(db.o): In function `dbm_exists':
db.c:(.text+0x3d4): undefined reference to `gdbm_open'
db.c:(.text+0x3f2): undefined reference to `gdbm_exists'
db.c:(.text+0x3fc): undefined reference to `gdbm_close'
packages/packages.a(db.o): In function `dbm_query':
db.c:(.text+0x486): undefined reference to `gdbm_open'
db.c:(.text+0x4a8): undefined reference to `gdbm_fetch'
db.c:(.text+0x4b3): undefined reference to `gdbm_close'
packages/packages.a(db.o): In function `dbm_store':
db.c:(.text+0x665): undefined reference to `gdbm_open'
db.c:(.text+0x6de): undefined reference to `gdbm_store'
db.c:(.text+0x6e9): undefined reference to `gdbm_close'
packages/packages.a(db.o): In function `dbm_delete':
db.c:(.text+0x7da): undefined reference to `gdbm_open'
db.c:(.text+0x7fa): undefined reference to `gdbm_delete'
db.c:(.text+0x804): undefined reference to `gdbm_close'
packages/packages.a(db.o): In function `dbm_keys':
db.c:(.text+0x8bf): undefined reference to `gdbm_open'
db.c:(.text+0x8d6): undefined reference to `gdbm_firstkey'
db.c:(.text+0x8ef): undefined reference to `gdbm_nextkey'
db.c:(.text+0x93e): undefined reference to `gdbm_firstkey'
db.c:(.text+0x957): undefined reference to `gdbm_nextkey'
db.c:(.text+0x9cf): undefined reference to `gdbm_close'
collect2: error: ld returned 1 exit status
gmake[1]: *** [GNUmakefile:114: driver] Error 1
gmake[1]: Leaving directory '/usr/home/starmud/fluffos1'
gmake: *** [GNUmakefile:84: main_build] Error 2
$
I'm unsure as to why these come up as 'undefined reference'.