]> jfr.im git - irc/quakenet/newserv.git/blame - dbapi2/dbapi2.c
Use correct constness and unsignedness in dbapi.
[irc/quakenet/newserv.git] / dbapi2 / dbapi2.c
CommitLineData
404d307c
CP
1#define MAX_PROVIDERS 10
2#define PROVIDER_NAME_LEN 100
3
4#define DBAPI_SNPRINTF_MAX_ARGS 20
5#define DBAPI_SNPRINTF_MAX_ARG_LENGTH 2048
6
7#include <string.h>
8#include <stdlib.h>
9#include <stdarg.h>
10
11#include "../core/error.h"
12#include "../lib/strlfunc.h"
13#include "../lib/stringbuf.h"
14#include "dbapi2.h"
15
16struct DBAPIProviderData {
17 char name[PROVIDER_NAME_LEN+1];
18};
19
20static DBAPIProvider *providerobjs[MAX_PROVIDERS];
21static struct DBAPIProviderData providerdata[MAX_PROVIDERS];
22
23void _init(void) {
24 memset(providerobjs, 0, sizeof(providerobjs));
25}
26
27void _fini(void) {
28 /* everything should be unregistered already */
29}
30
31int registerdbprovider(const char *name, DBAPIProvider *provider) {
32 int i;
33
34 for(i=0;i<MAX_PROVIDERS;i++) {
adf9e9ea 35 if(providerobjs[i])
404d307c
CP
36 continue;
37
38 providerobjs[i] = provider;
39 providerobjs[i]->__providerdata = &providerdata[i];
40
41 strlcpy(providerobjs[i]->__providerdata->name, name, PROVIDER_NAME_LEN);
42
39c33a3d
CP
43 Error("dbapi2", ERR_INFO, "Database API registered: %s", name);
44
404d307c
CP
45 return i;
46 }
47
48 Error("dbapi2", ERR_WARNING, "No remaining space for new database provider: %s", name);
49 return -1;
50}
51
52void deregisterdbprovider(int handle) {
53 if(handle < 0)
54 return;
55
56 providerobjs[handle] = NULL;
57}
58
59static void dbclose(DBAPIConn *db) {
60 db->__close(db);
4a532778 61 free((DBAPIConn *)db);
404d307c
CP
62}
63
4a532778 64static void dbsimplequery(const DBAPIConn *db, const char *format, ...) {
adf9e9ea
CP
65 va_list ap;
66
67 va_start(ap, format);
68 db->__query(db, NULL, NULL, format, ap);
69 va_end(ap);
70}
71
4a532778 72static void dbquery(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *format, ...) {
adf9e9ea
CP
73 va_list ap;
74
75 va_start(ap, format);
76 db->__query(db, cb, data, format, ap);
77 va_end(ap);
78}
79
39c33a3d
CP
80DBAPIConn *dbapi2open(const char *provider, const char *database) {
81 int i, found = -1;
404d307c
CP
82 DBAPIConn *db;
83 DBAPIProvider *p;
84
39c33a3d
CP
85 if(provider) {
86 for(i=0;i<MAX_PROVIDERS;i++) {
87 if(providerobjs[i] && !strcmp(provider, providerobjs[i]->__providerdata->name)) {
88 found = i;
89 break;
90 }
91 }
92 if(found == -1) {
93 Error("dbapi2", ERR_WARNING, "Couldn't find forced database provider %s", provider);
94 return NULL;
95 }
96 } else {
97 for(i=0;i<MAX_PROVIDERS;i++) {
98 if(providerobjs[i]) {
99 found = i;
100 break;
101 }
404d307c 102 }
404d307c 103
39c33a3d
CP
104 if(found == -1) {
105 Error("dbapi2", ERR_WARNING, "No database providers found.");
106 return NULL;
107 }
404d307c
CP
108 }
109
adf9e9ea 110 p = providerobjs[found];
404d307c
CP
111
112 db = calloc(1, sizeof(DBAPIConn));
113 if(!db)
114 return NULL;
115
116 db->close = dbclose;
adf9e9ea 117 db->query = dbquery;
404d307c
CP
118 db->createtable = p->createtable;
119 db->loadtable = p->loadtable;
120 db->escapestring = p->escapestring;
adf9e9ea 121 db->squery = dbsimplequery;
4277aef7 122 db->tablename = p->tablename;
404d307c 123
adf9e9ea 124 db->__query = p->query;
404d307c
CP
125 db->__close = p->close;
126 db->__quotestring = p->quotestring;
127
128 strlcpy(db->name, database, DBNAME_LEN);
129
130 db->handle = p->new(db);
131 if(!db->handle) {
132 free(db);
133 Error("dbapi2", ERR_WARNING, "Unable to initialise database %s, provider: %s", database, p->__providerdata->name);
134 return NULL;
135 }
136
39c33a3d
CP
137 Error("dbapi2", ERR_INFO, "Database %s opened with provider %s.", database, p->__providerdata->name);
138
404d307c
CP
139 return db;
140}
141
4a532778 142static void dbvsnprintf(const DBAPIConn *db, char *buf, size_t size, const char *format, const char *types, va_list ap) {
404d307c
CP
143 StringBuf b;
144 const char *p;
145 static char convbuf[DBAPI_SNPRINTF_MAX_ARGS][DBAPI_SNPRINTF_MAX_ARG_LENGTH+10];
146 int arg, argcount;
147
148 if(size == 0)
149 return;
150
151 {
152 int i;
153
154 int d;
155 char *s;
156 double g;
157 unsigned int u;
158 size_t l;
159 int fallthrough;
160
161 for(i=0;i<DBAPI_SNPRINTF_MAX_ARGS;i++)
162 convbuf[i][0] = '\0';
163
164 argcount=0;
165 for(;*types;types++) {
166 char *cb = convbuf[argcount];
167
168 if(argcount++ >= DBAPI_SNPRINTF_MAX_ARGS) {
169 /* calls exit(0) */
170 Error("dbapi2", ERR_STOP, "Maximum arguments reached in dbvsnprintf, database: %s", db->name);
171 }
172
173 fallthrough = 0;
174 switch(*types) {
175 case 's':
176 s = va_arg(ap, char *);
177 l = strlen(s);
178 fallthrough = 1;
179
180 /* falling through */
181 case 'S':
182 if(!fallthrough) {
183 s = va_arg(ap, char *);
184 l = va_arg(ap, size_t);
185 }
186
187 /* now... this is a guess, but we should catch it most of the time */
188 if((l > (DBAPI_SNPRINTF_MAX_ARG_LENGTH / 2)) || !db->__quotestring(db, cb, sizeof(convbuf[0]), s, l)) {
189 Error("dbapi2", ERR_WARNING, "Long string truncated (database: %s).", db->name);
190 l = DBAPI_SNPRINTF_MAX_ARG_LENGTH;
191 }
192
193 break;
194 case 'd':
195 d = va_arg(ap, int);
196 snprintf(cb, DBAPI_SNPRINTF_MAX_ARG_LENGTH, "%d", d);
197 break;
198 case 'u':
199 u = va_arg(ap, unsigned int);
200 snprintf(cb, DBAPI_SNPRINTF_MAX_ARG_LENGTH, "%u", u);
201 break;
202 case 'g':
203 g = va_arg(ap, double);
204 snprintf(cb, DBAPI_SNPRINTF_MAX_ARG_LENGTH, "%.1f", g);
205 break;
206 default:
207 /* calls exit(0) */
208 Error("dbapi2", ERR_STOP, "Bad format specifier '%c' supplied in dbvsnprintf, format: '%s', database: %s", *types, format, db->name);
209 }
210 }
211 }
212
213 sbinit(&b, buf, size);
214
215 for(arg=0,p=format;*p;p++) {
216 if(*p != '?') {
217 if(!sbaddchar(&b, *p))
218 break;
219 continue;
220 }
221 p++;
222 if(arg >= argcount) {
223 /* calls exit(0) */
224 Error("dbapi2", ERR_STOP, "Gone over number of arguments in dbvsnprintf, database: %s", db->name);
225 }
226
227 if(!sbaddstr(&b, convbuf[arg])) {
228 /* calls exit(0) */
229 Error("dbapi2", ERR_STOP, "Possible truncation in dbvsnprintf, database: %s", db->name);
230 }
231
232 arg++;
233 }
234
235 sbterminate(&b);
236}
237
4a532778 238void dbsnprintf(const DBAPIConn *db, char *buf, size_t size, const char *format, const char *types, ...) {
404d307c
CP
239 va_list ap;
240
241 va_start(ap, types);
242 dbvsnprintf(db, buf, size, format, types, ap);
243 va_end(ap);
244}