summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/c/cgi.c7
-rw-r--r--src/c/fastcgi.c9
-rw-r--r--src/c/http.c8
-rw-r--r--src/c/request.c22
-rw-r--r--src/c/urweb.c145
-rw-r--r--src/cjr_print.sml50
-rw-r--r--src/compiler.sml2
-rw-r--r--src/mysql.sml12
-rw-r--r--src/postgres.sml196
-rw-r--r--src/sqlite.sml12
10 files changed, 228 insertions, 235 deletions
diff --git a/src/c/cgi.c b/src/c/cgi.c
index 38cb7da4..1d7d9810 100644
--- a/src/c/cgi.c
+++ b/src/c/cgi.c
@@ -5,8 +5,11 @@
#include <unistd.h>
#include <stdarg.h>
+#include "urweb.h"
#include "request.h"
+extern uw_app uw_application;
+
static char *uppercased;
static size_t uppercased_len;
@@ -51,7 +54,7 @@ static void log_debug(void *data, const char *fmt, ...) {
}
int main(int argc, char *argv[]) {
- uw_context ctx = uw_request_new_context(NULL, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
uw_request_context rc = uw_new_request_context();
request_result rr;
char *method = getenv("REQUEST_METHOD"),
@@ -97,7 +100,7 @@ int main(int argc, char *argv[]) {
uw_set_on_success("");
uw_set_headers(ctx, get_header, NULL);
- uw_request_init(NULL, log_error, log_debug);
+ uw_request_init(&uw_application, NULL, log_error, log_debug);
body[body_pos] = 0;
rr = uw_request(rc, ctx, method, path, query_string, body, body_pos,
diff --git a/src/c/fastcgi.c b/src/c/fastcgi.c
index 1a8a8316..b6b6e9a8 100644
--- a/src/c/fastcgi.c
+++ b/src/c/fastcgi.c
@@ -10,6 +10,7 @@
#include <unistd.h>
#include <signal.h>
#include <stdarg.h>
+#include <ctype.h>
#include <pthread.h>
@@ -19,6 +20,8 @@
#include "fastcgi.h"
+extern uw_app uw_application;
+
typedef struct {
unsigned char version;
unsigned char type;
@@ -300,7 +303,7 @@ static void *worker(void *data) {
int me = *(int *)data;
FCGI_Input *in = fastcgi_input();
FCGI_Output *out = fastcgi_output();
- uw_context ctx = uw_request_new_context(out, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(&uw_application, out, log_error, log_debug);
uw_request_context rc = uw_new_request_context();
headers hs;
size_t body_size = 0;
@@ -489,7 +492,7 @@ static void sigint(int signum) {
exit(0);
}
-static loggers ls = {NULL, log_error, log_debug};
+static loggers ls = {&uw_application, NULL, log_error, log_debug};
int main(int argc, char *argv[]) {
// The skeleton for this function comes from Beej's sockets tutorial.
@@ -538,7 +541,7 @@ int main(int argc, char *argv[]) {
}
uw_set_on_success("");
- uw_request_init(NULL, log_error, log_debug);
+ uw_request_init(&uw_application, NULL, log_error, log_debug);
names = calloc(nthreads, sizeof(int));
diff --git a/src/c/http.c b/src/c/http.c
index 9550bd4f..70001961 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -16,6 +16,8 @@
#include "request.h"
#include "queue.h"
+extern uw_app uw_application;
+
int uw_backlog = 10;
static char *get_header(void *data, const char *h) {
@@ -61,7 +63,7 @@ static void log_debug(void *data, const char *fmt, ...) {
static void *worker(void *data) {
int me = *(int *)data;
- uw_context ctx = uw_request_new_context(NULL, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
size_t buf_size = 2;
char *buf = malloc(buf_size);
uw_request_context rc = uw_new_request_context();
@@ -214,7 +216,7 @@ static void sigint(int signum) {
exit(0);
}
-static loggers ls = {NULL, log_error, log_debug};
+static loggers ls = {&uw_application, NULL, log_error, log_debug};
int main(int argc, char *argv[]) {
// The skeleton for this function comes from Beej's sockets tutorial.
@@ -262,7 +264,7 @@ int main(int argc, char *argv[]) {
}
}
- uw_request_init(NULL, log_error, log_debug);
+ uw_request_init(&uw_application, NULL, log_error, log_debug);
names = calloc(nthreads, sizeof(int));
diff --git a/src/c/request.c b/src/c/request.c
index a314bb19..5c8159cc 100644
--- a/src/c/request.c
+++ b/src/c/request.c
@@ -31,9 +31,10 @@ static int try_rollback(uw_context ctx, void *logger_data, uw_logger log_error)
return r;
}
-uw_context uw_request_new_context(void *logger_data, uw_logger log_error, uw_logger log_debug) {
+uw_context uw_request_new_context(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) {
uw_context ctx = uw_init();
int retries_left = MAX_RETRIES;
+ uw_set_app(ctx, app);
while (1) {
failure_kind fk = uw_begin_init(ctx);
@@ -95,26 +96,27 @@ static void init_crypto(void *logger_data, uw_logger log_error) {
}
}
-void uw_request_init(void *logger_data, uw_logger log_error, uw_logger log_debug) {
+void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) {
uw_context ctx;
failure_kind fk;
uw_global_init();
+ uw_app_init(app);
- ctx = uw_request_new_context(logger_data, log_error, log_debug);
+ ctx = uw_request_new_context(app, logger_data, log_error, log_debug);
if (!ctx)
exit(1);
for (fk = uw_initialize(ctx); fk == UNLIMITED_RETRY; fk = uw_initialize(ctx)) {
log_debug(logger_data, "Unlimited retry during init: %s\n", uw_error_message(ctx));
- uw_db_rollback(ctx);
+ uw_rollback(ctx);
uw_reset(ctx);
}
if (fk != SUCCESS) {
log_error(logger_data, "Failed to initialize database! %s\n", uw_error_message(ctx));
- uw_db_rollback(ctx);
+ uw_rollback(ctx);
exit(1);
}
@@ -151,8 +153,6 @@ void uw_free_request_context(uw_request_context r) {
free(r);
}
-extern char *uw_url_prefix;
-
request_result uw_request(uw_request_context rc, uw_context ctx,
char *method, char *path, char *query_string,
char *body, size_t body_len,
@@ -168,6 +168,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
char *boundary = NULL;
size_t boundary_len;
char *inputs;
+ const char *prefix = uw_get_url_prefix(ctx);
uw_set_currentUrl(ctx, path);
@@ -208,8 +209,8 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
return FAILED;
}
- if (!strncmp(path, uw_url_prefix, strlen(uw_url_prefix))
- && !strcmp(path + strlen(uw_url_prefix), ".msgs")) {
+ if (!strncmp(path, prefix, strlen(prefix))
+ && !strcmp(path + strlen(prefix), ".msgs")) {
char *id = uw_Basis_requestHeader(ctx, "UrWeb-Client");
char *pass = uw_Basis_requestHeader(ctx, "UrWeb-Pass");
@@ -435,13 +436,14 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
}
typedef struct {
+ uw_app *app;
void *logger_data;
uw_logger log_error, log_debug;
} loggers;
void *client_pruner(void *data) {
loggers *ls = (loggers *)data;
- uw_context ctx = uw_request_new_context(ls->logger_data, ls->log_error, ls->log_debug);
+ uw_context ctx = uw_request_new_context(ls->app, ls->logger_data, ls->log_error, ls->log_debug);
if (!ctx)
exit(1);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 4a0306e0..455b3e1e 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -1,4 +1,4 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <stdio.h>
@@ -9,6 +9,8 @@
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <pthread.h>
@@ -287,14 +289,14 @@ static void client_send(client *c, buf *msg) {
// Global entry points
-extern void uw_client_init();
-
void uw_global_init() {
srand(time(NULL) ^ getpid());
clients = malloc(0);
+}
- uw_client_init();
+void uw_app_init(uw_app *app) {
+ app->client_init();
}
@@ -349,13 +351,15 @@ typedef struct {
} global;
struct uw_context {
+ uw_app *app;
+
char *(*get_header)(void *, const char *);
void *get_header_data;
buf outHeaders, page, heap, script;
int returning_indirectly;
input *inputs, *subinputs, *cur_container;
- size_t n_subinputs, used_subinputs;
+ size_t sz_inputs, n_subinputs, used_subinputs;
int source_count;
@@ -367,15 +371,13 @@ struct uw_context {
cleanup *cleanup, *cleanup_front, *cleanup_back;
- const char *script_header, *url_prefix;
+ const char *script_header;
int needs_push, needs_sig;
size_t n_deltas, used_deltas;
delta *deltas;
- int timeout;
-
client *client;
transactional *transactionals;
@@ -389,11 +391,11 @@ struct uw_context {
char error_message[ERROR_BUF_LEN];
};
-extern int uw_inputs_len, uw_timeout;
-
uw_context uw_init() {
uw_context ctx = malloc(sizeof(struct uw_context));
+ ctx->app = NULL;
+
ctx->get_header = NULL;
ctx->get_header_data = NULL;
@@ -404,10 +406,10 @@ uw_context uw_init() {
buf_init(&ctx->script, 1);
ctx->script.start[0] = 0;
- ctx->inputs = calloc(uw_inputs_len, sizeof(input));
+ ctx->inputs = malloc(0);
ctx->cur_container = NULL;
ctx->subinputs = malloc(0);
- ctx->n_subinputs = ctx->used_subinputs = 0;
+ ctx->sz_inputs = ctx->n_subinputs = ctx->used_subinputs = 0;
ctx->db = NULL;
@@ -416,7 +418,6 @@ uw_context uw_init() {
ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
ctx->script_header = "";
- ctx->url_prefix = "/";
ctx->needs_push = 0;
ctx->needs_sig = 0;
@@ -427,8 +428,6 @@ uw_context uw_init() {
ctx->n_deltas = ctx->used_deltas = 0;
ctx->deltas = malloc(0);
- ctx->timeout = uw_timeout;
-
ctx->client = NULL;
ctx->error_message[0] = 0;
@@ -444,6 +443,16 @@ uw_context uw_init() {
return ctx;
}
+void uw_set_app(uw_context ctx, uw_app *app) {
+ ctx->app = app;
+
+ if (app->inputs_len > ctx->sz_inputs) {
+ ctx->sz_inputs = app->inputs_len;
+ ctx->inputs = realloc(ctx->inputs, ctx->sz_inputs * sizeof(input));
+ memset(ctx->inputs, 0, ctx->sz_inputs * sizeof(input));
+ }
+}
+
void uw_set_db(uw_context ctx, void *db) {
ctx->db = db;
}
@@ -499,19 +508,16 @@ void uw_reset_keep_request(uw_context ctx) {
void uw_reset(uw_context ctx) {
uw_reset_keep_request(ctx);
- memset(ctx->inputs, 0, uw_inputs_len * sizeof(input));
+ memset(ctx->inputs, 0, ctx->app->inputs_len * sizeof(input));
memset(ctx->subinputs, 0, ctx->n_subinputs * sizeof(input));
ctx->used_subinputs = 0;
}
-void uw_db_init(uw_context);
-void uw_handle(uw_context, char *);
-
failure_kind uw_begin_init(uw_context ctx) {
int r = setjmp(ctx->jmp_buf);
if (r == 0)
- uw_db_init(ctx);
+ ctx->app->db_init(ctx);
return r;
}
@@ -521,8 +527,6 @@ void uw_set_headers(uw_context ctx, char *(*get_header)(void *, const char *), v
ctx->get_header_data = get_header_data;
}
-int uw_db_begin(uw_context);
-
static void uw_set_error(uw_context ctx, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@@ -600,10 +604,10 @@ failure_kind uw_begin(uw_context ctx, char *path) {
int r = setjmp(ctx->jmp_buf);
if (r == 0) {
- if (uw_db_begin(ctx))
+ if (ctx->app->db_begin(ctx))
uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
- uw_handle(ctx, path);
+ ctx->app->handle(ctx, path);
}
return r;
@@ -628,8 +632,6 @@ char *uw_error_message(uw_context ctx) {
return ctx->error_message;
}
-extern int uw_input_num(const char*);
-
static input *INP(uw_context ctx) {
if (ctx->cur_container == NULL)
return ctx->inputs;
@@ -674,7 +676,7 @@ static input *check_input_space(uw_context ctx, size_t len) {
if (ctx->subinputs != new_subinputs) {
for (i = 0; i < ctx->used_subinputs; ++i)
adjust_input(&new_subinputs[i], ctx->subinputs, new_subinputs, ctx->used_subinputs);
- for (i = 0; i < uw_inputs_len; ++i)
+ for (i = 0; i < ctx->app->inputs_len; ++i)
adjust_input(&ctx->inputs[i], ctx->subinputs, new_subinputs, ctx->used_subinputs);
adjust_pointer(&ctx->cur_container, ctx->subinputs, new_subinputs, ctx->used_subinputs);
@@ -696,7 +698,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
//printf("Input name %s\n", name);
if (!strcasecmp(name, ".b")) {
- int n = uw_input_num(value);
+ int n = ctx->app->input_num(value);
input *inps;
if (n < 0) {
@@ -704,12 +706,12 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
return -1;
}
- if (n >= uw_inputs_len) {
+ if (n >= ctx->app->inputs_len) {
uw_set_error(ctx, "For subform name %s, index %d is out of range", value, n);
return -1;
}
- inps = check_input_space(ctx, uw_inputs_len);
+ inps = check_input_space(ctx, ctx->app->inputs_len);
INP(ctx)[n].kind = SUBFORM;
INP(ctx)[n].data.subform.parent = ctx->cur_container;
@@ -741,14 +743,14 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
return -1;
}
} else if (!strcasecmp(name, ".s")) {
- int n = uw_input_num(value);
+ int n = ctx->app->input_num(value);
if (n < 0) {
uw_set_error(ctx, "Bad subforms name %s", value);
return -1;
}
- if (n >= uw_inputs_len) {
+ if (n >= ctx->app->inputs_len) {
uw_set_error(ctx, "For subforms name %s, index %d is out of range", value, n);
return -1;
}
@@ -770,7 +772,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
return -1;
}
- inps = check_input_space(ctx, uw_inputs_len + 1);
+ inps = check_input_space(ctx, ctx->app->inputs_len + 1);
inps->kind = ENTRY;
inps->data.entry.parent = ctx->cur_container;
@@ -780,7 +782,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
inps->data.entry.fields = inps+1;
ctx->cur_container = inps;
} else {
- int n = uw_input_num(name);
+ int n = ctx->app->input_num(name);
if (n < 0) {
if (!strcmp(name, "null"))
@@ -789,7 +791,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
return -1;
}
- if (n >= uw_inputs_len) {
+ if (n >= ctx->app->inputs_len) {
uw_set_error(ctx, "For input name %s, index %d is out of range", name, n);
return -1;
}
@@ -804,7 +806,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) {
char *uw_get_input(uw_context ctx, int n) {
if (n < 0)
uw_error(ctx, FATAL, "Negative input index %d", n);
- if (n >= uw_inputs_len)
+ if (n >= ctx->app->inputs_len)
uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
switch (INP(ctx)[n].kind) {
@@ -828,7 +830,7 @@ char *uw_get_input(uw_context ctx, int n) {
char *uw_get_optional_input(uw_context ctx, int n) {
if (n < 0)
uw_error(ctx, FATAL, "Negative input index %d", n);
- if (n >= uw_inputs_len)
+ if (n >= ctx->app->inputs_len)
uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
switch (INP(ctx)[n].kind) {
@@ -850,14 +852,14 @@ char *uw_get_optional_input(uw_context ctx, int n) {
}
int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) {
- int n = uw_input_num(name);
+ int n = ctx->app->input_num(name);
if (n < 0) {
uw_set_error(ctx, "Bad file input name %s", name);
return -1;
}
- if (n >= uw_inputs_len) {
+ if (n >= ctx->app->inputs_len) {
uw_set_error(ctx, "For file input name %s, index %d is out of range", name, n);
return -1;
}
@@ -870,7 +872,6 @@ int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) {
void *uw_malloc(uw_context ctx, size_t len);
-
static void parents(input *inp) {
printf("Stack: %p\n", inp);
while (inp) {
@@ -902,7 +903,7 @@ static void parents(input *inp) {
uw_Basis_file uw_get_file_input(uw_context ctx, int n) {
if (n < 0)
uw_error(ctx, FATAL, "Negative file input index %d", n);
- if (n >= uw_inputs_len)
+ if (n >= ctx->app->inputs_len)
uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n);
switch (INP(ctx)[n].kind) {
@@ -930,7 +931,7 @@ uw_Basis_file uw_get_file_input(uw_context ctx, int n) {
void uw_enter_subform(uw_context ctx, int n) {
if (n < 0)
uw_error(ctx, FATAL, "Negative subform index %d", n);
- if (n >= uw_inputs_len)
+ if (n >= ctx->app->inputs_len)
uw_error(ctx, FATAL, "Out-of-bounds subform index %d", n);
switch (INP(ctx)[n].kind) {
@@ -969,7 +970,7 @@ int uw_enter_subforms(uw_context ctx, int n) {
if (n < 0)
uw_error(ctx, FATAL, "Negative subforms index %d", n);
- if (n >= uw_inputs_len)
+ if (n >= ctx->app->inputs_len)
uw_error(ctx, FATAL, "Out-of-bounds subforms index %d", n);
switch (INP(ctx)[n].kind) {
@@ -1028,8 +1029,8 @@ void uw_set_script_header(uw_context ctx, const char *s) {
ctx->script_header = s;
}
-void uw_set_url_prefix(uw_context ctx, const char *s) {
- ctx->url_prefix = s;
+const char *uw_get_url_prefix(uw_context ctx) {
+ return ctx->app->url_prefix;
}
void uw_set_needs_push(uw_context ctx, int n) {
@@ -1204,12 +1205,10 @@ uw_Basis_string uw_Basis_maybe_onunload(uw_context ctx, uw_Basis_string s) {
}
}
-extern uw_Basis_string uw_cookie_sig(uw_context);
-
const char *uw_Basis_get_settings(uw_context ctx, uw_unit u) {
if (ctx->client == NULL) {
if (ctx->needs_sig) {
- char *sig = uw_cookie_sig(ctx);
+ char *sig = ctx->app->cookie_sig(ctx);
char *r = uw_malloc(ctx, strlen(sig) + 8);
sprintf(r, "sig=\"%s\";", sig);
return r;
@@ -1217,14 +1216,14 @@ const char *uw_Basis_get_settings(uw_context ctx, uw_unit u) {
else
return "";
} else {
- char *sig = ctx->needs_sig ? uw_cookie_sig(ctx) : "";
- char *r = uw_malloc(ctx, 59 + 3 * INTS_MAX + strlen(ctx->url_prefix)
+ char *sig = ctx->needs_sig ? ctx->app->cookie_sig(ctx) : "";
+ char *r = uw_malloc(ctx, 59 + 3 * INTS_MAX + strlen(ctx->app->url_prefix)
+ (ctx->needs_sig ? strlen(sig) + 7 : 0));
sprintf(r, "client_id=%u;client_pass=%d;url_prefix=\"%s\";timeout=%d;%s%s%slistener();",
ctx->client->id,
ctx->client->pass,
- ctx->url_prefix,
- ctx->timeout,
+ ctx->app->url_prefix,
+ ctx->app->timeout,
ctx->needs_sig ? "sig=\"" : "",
sig,
ctx->needs_sig ? "\";" : "");
@@ -2766,9 +2765,6 @@ uw_unit uw_Basis_send(uw_context ctx, uw_Basis_channel chn, uw_Basis_string msg)
return uw_unit_v;
}
-int uw_db_commit(uw_context);
-int uw_db_rollback(uw_context);
-
void uw_commit(uw_context ctx) {
unsigned i;
@@ -2782,7 +2778,7 @@ void uw_commit(uw_context ctx) {
if (ctx->transactionals[i].commit)
ctx->transactionals[i].commit(ctx->transactionals[i].data);
- if (uw_db_commit(ctx))
+ if (ctx->app->db_commit(ctx))
uw_error(ctx, FATAL, "Error running SQL COMMIT");
for (i = 0; i < ctx->used_deltas; ++i) {
@@ -2855,7 +2851,7 @@ int uw_rollback(uw_context ctx) {
if (ctx->transactionals[i].free)
ctx->transactionals[i].free(ctx->transactionals[i].data);
- return uw_db_rollback(ctx);
+ return ctx->app->db_rollback(ctx);
}
void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback,
@@ -2874,16 +2870,14 @@ void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, u
// "Garbage collection"
-void uw_expunger(uw_context ctx, uw_Basis_client cli);
-
static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli) {
int r = setjmp(ctx->jmp_buf);
if (r == 0) {
- if (uw_db_begin(ctx))
+ if (ctx->app->db_begin(ctx))
uw_error(ctx, FATAL, "Error running SQL BEGIN");
- uw_expunger(ctx, cli);
- if (uw_db_commit(ctx))
+ ctx->app->expunger(ctx, cli);
+ if (ctx->app->db_commit(ctx))
uw_error(ctx, FATAL, "Error running SQL COMMIT");
}
@@ -2894,7 +2888,7 @@ void uw_prune_clients(uw_context ctx) {
client *c, *next, *prev = NULL;
time_t cutoff;
- cutoff = time(NULL) - uw_timeout;
+ cutoff = time(NULL) - ctx->app->timeout;
pthread_mutex_lock(&clients_mutex);
@@ -2911,14 +2905,14 @@ void uw_prune_clients(uw_context ctx) {
while (fk == UNLIMITED_RETRY) {
fk = uw_expunge(ctx, c->id);
if (fk == UNLIMITED_RETRY) {
- uw_db_rollback(ctx);
+ ctx->app->db_rollback(ctx);
printf("Unlimited retry during expunge: %s\n", uw_error_message(ctx));
}
}
if (fk == SUCCESS)
free_client(c);
else {
- uw_db_rollback(ctx);
+ ctx->app->db_rollback(ctx);
fprintf(stderr, "Expunge blocked by error: %s\n", uw_error_message(ctx));
}
}
@@ -2930,25 +2924,20 @@ void uw_prune_clients(uw_context ctx) {
pthread_mutex_unlock(&clients_mutex);
}
-void uw_initializer(uw_context ctx);
-
failure_kind uw_initialize(uw_context ctx) {
int r = setjmp(ctx->jmp_buf);
if (r == 0) {
- if (uw_db_begin(ctx))
+ if (ctx->app->db_begin(ctx))
uw_error(ctx, FATAL, "Error running SQL BEGIN");
- uw_initializer(ctx);
- if (uw_db_commit(ctx))
+ ctx->app->initializer(ctx);
+ if (ctx->app->db_commit(ctx))
uw_error(ctx, FATAL, "Error running SQL COMMIT");
}
return r;
}
-extern int uw_check_url(const char *);
-extern int uw_check_mime(const char *);
-
static int url_bad(uw_Basis_string s) {
for (; *s; ++s)
if (!isgraph(*s))
@@ -2960,7 +2949,7 @@ static int url_bad(uw_Basis_string s) {
uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) {
if (url_bad(s))
uw_error(ctx, FATAL, "Invalid URL %s", uw_Basis_htmlifyString(ctx, s));
- if (uw_check_url(s))
+ if (ctx->app->check_url(s))
return s;
else
uw_error(ctx, FATAL, "Disallowed URL %s", uw_Basis_htmlifyString(ctx, s));
@@ -2969,7 +2958,7 @@ uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) {
uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) {
if (url_bad(s))
return NULL;
- if (uw_check_url(s))
+ if (ctx->app->check_url(s))
return s;
else
return NULL;
@@ -2987,7 +2976,7 @@ uw_Basis_string uw_Basis_blessMime(uw_context ctx, uw_Basis_string s) {
if (!mime_format(s))
uw_error(ctx, FATAL, "MIME type \"%s\" contains invalid character", uw_Basis_htmlifyString(ctx, s));
- if (uw_check_mime(s))
+ if (ctx->app->check_mime(s))
return s;
else
uw_error(ctx, FATAL, "Disallowed MIME type %s", uw_Basis_htmlifyString(ctx, s));
@@ -2997,7 +2986,7 @@ uw_Basis_string uw_Basis_checkMime(uw_context ctx, uw_Basis_string s) {
if (!mime_format(s))
return NULL;
- if (uw_check_mime(s))
+ if (ctx->app->check_mime(s))
return s;
else
return NULL;
@@ -3020,7 +3009,7 @@ uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) {
}
uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) {
- return uw_cookie_sig(ctx);
+ return ctx->app->cookie_sig(ctx);
}
uw_Basis_string uw_Basis_fileName(uw_context ctx, uw_Basis_file f) {
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index 2d547519..30e34fad 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2604,10 +2604,6 @@ fun p_file env (ds, ps) =
string scripts
end,
string "\");",
- newline,
- string "uw_set_url_prefix(ctx, \"",
- string (Settings.getUrlPrefix ()),
- string "\");",
newline]),
string "uw_set_needs_push(ctx, ",
string (case side of
@@ -2706,7 +2702,7 @@ fun p_file env (ds, ps) =
NONE cookies
fun makeChecker (name, rules : Settings.rule list) =
- box [string "int ",
+ box [string "static int ",
string name,
string "(const char *s) {",
newline,
@@ -2772,34 +2768,22 @@ fun p_file env (ds, ps) =
newline,
string "int uw_db_begin(uw_context ctx) { return 0; };",
newline,
+ string "void uw_db_close(uw_context ctx) { };",
+ newline,
string "int uw_db_commit(uw_context ctx) { return 0; };",
newline,
string "int uw_db_rollback(uw_context ctx) { return 0; };"],
newline,
newline,
- string "const char *uw_url_prefix = \"",
- string (Settings.getUrlPrefix ()),
- string "\";",
- newline,
- newline,
-
string "static const char begin_xhtml[] = \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" ?>\\n<!DOCTYPE html PUBLIC \\\"-//W3C//DTD XHTML 1.0 Transitional//EN\\\" \\\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\\">\\n<html xmlns=\\\"http://www.w3.org/1999/xhtml\\\" xml:lang=\\\"en\\\" lang=\\\"en\\\">\";",
newline,
newline,
p_list_sep newline (fn x => x) pds,
newline,
- string "int uw_inputs_len = ",
- string (Int.toString (SM.foldl Int.max 0 fnums + 1)),
- string ";",
- newline,
- string "int uw_timeout = ",
- string (Int.toString (Settings.getTimeout ())),
- string ";",
- newline,
newline,
- string "int uw_input_num(char *name) {",
+ string "static int uw_input_num(const char *name) {",
newline,
makeSwitch (fnums, 0),
string "}",
@@ -2816,7 +2800,7 @@ fun p_file env (ds, ps) =
newline,
string "extern int uw_hash_blocksize;",
newline,
- string "uw_Basis_string uw_cookie_sig(uw_context ctx) {",
+ string "static uw_Basis_string uw_cookie_sig(uw_context ctx) {",
newline,
box [string "uw_Basis_string r = uw_malloc(ctx, uw_hash_blocksize);",
newline,
@@ -2832,7 +2816,7 @@ fun p_file env (ds, ps) =
newline,
newline,
- string "void uw_handle(uw_context ctx, char *request) {",
+ string "static void uw_handle(uw_context ctx, char *request) {",
newline,
string "if (!strcmp(request, \"",
string (OS.Path.joinDirFile {dir = Settings.getUrlPrefix (),
@@ -2856,7 +2840,7 @@ fun p_file env (ds, ps) =
newline,
if hasDb then
- box [string "void uw_expunger(uw_context ctx, uw_Basis_client cli) {",
+ box [string "static void uw_expunger(uw_context ctx, uw_Basis_client cli) {",
newline,
box [p_enamed env (!expunge),
string "(ctx, cli);",
@@ -2865,7 +2849,7 @@ fun p_file env (ds, ps) =
newline,
newline,
- string "void uw_initializer(uw_context ctx) {",
+ string "static void uw_initializer(uw_context ctx) {",
newline,
box [p_list_sep (box []) (fn e => box [p_exp env e,
string ";",
@@ -2876,10 +2860,22 @@ fun p_file env (ds, ps) =
string "}",
newline]
else
- box [string "void uw_expunger(uw_context ctx, uw_Basis_client cli) { };",
+ box [string "static void uw_expunger(uw_context ctx, uw_Basis_client cli) { };",
newline,
- string "void uw_initializer(uw_context ctx) { };",
- newline]]
+ string "static void uw_initializer(uw_context ctx) { };",
+ newline],
+
+ string "uw_app uw_application = {",
+ p_list_sep (box [string ",", newline]) string
+ [Int.toString (SM.foldl Int.max 0 fnums + 1),
+ Int.toString (Settings.getTimeout ()),
+ "\"" ^ Settings.getUrlPrefix () ^ "\"",
+ "uw_client_init", "uw_initializer", "uw_expunger",
+ "uw_db_init", "uw_db_begin", "uw_db_commit", "uw_db_rollback", "uw_db_close",
+ "uw_handle",
+ "uw_input_num", "uw_cookie_sig", "uw_check_url", "uw_check_mime"],
+ string "};",
+ newline]
end
fun p_sql env (ds, _) =
diff --git a/src/compiler.sml b/src/compiler.sml
index 10fc66f0..a596a21d 100644
--- a/src/compiler.sml
+++ b/src/compiler.sml
@@ -1028,7 +1028,7 @@ fun compileC {cname, oname, ename, libs, profile, debug, link = link'} =
val urweb_o = clibFile "urweb.o"
val memmem_o = clibFile "memmem.o"
- val compile = "gcc " ^ Config.gccArgs ^ " -Wstrict-prototypes -Werror -O3 -fno-inline -I " ^ Config.includ
+ val compile = "gcc " ^ Config.gccArgs ^ " -Wimplicit -Werror -O3 -fno-inline -I " ^ Config.includ
^ " -c " ^ cname ^ " -o " ^ oname
val link = "gcc -Werror -O3 -lm -lmhash -pthread " ^ Config.gccArgs ^ " " ^ libs ^ " " ^ urweb_o ^ " " ^ oname
^ " " ^ memmem_o ^ " " ^ #link proto ^ " -o " ^ ename
diff --git a/src/mysql.sml b/src/mysql.sml
index 40409ff0..b894bfac 100644
--- a/src/mysql.sml
+++ b/src/mysql.sml
@@ -379,7 +379,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_client_init(void) {",
+ string "static void uw_client_init(void) {",
newline,
box [string "uw_sqlfmtInt = \"%lld%n\";",
newline,
@@ -502,7 +502,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_db_init(uw_context ctx) {",
+ string "static void uw_db_init(uw_context ctx) {",
newline,
string "MYSQL *mysql = mysql_init(NULL);",
newline,
@@ -554,7 +554,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_db_close(uw_context ctx) {",
+ string "static void uw_db_close(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -573,7 +573,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "int uw_db_begin(uw_context ctx) {",
+ string "static int uw_db_begin(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -586,7 +586,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "int uw_db_commit(uw_context ctx) {",
+ string "static int uw_db_commit(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -596,7 +596,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "int uw_db_rollback(uw_context ctx) {",
+ string "static int uw_db_rollback(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
diff --git a/src/postgres.sml b/src/postgres.sml
index c4bbb067..59fa3330 100644
--- a/src/postgres.sml
+++ b/src/postgres.sml
@@ -249,27 +249,7 @@ fun checkRel (table, checkNullable) (s, xts) =
fun init {dbstring, prepared = ss, tables, views, sequences} =
box [if #persistent (currentProtocol ()) then
- box [string "void uw_client_init(void) {",
- newline,
- box [string "uw_sqlfmtInt = \"%lld::int8%n\";",
- newline,
- string "uw_sqlfmtFloat = \"%g::float8%n\";",
- newline,
- string "uw_Estrings = 1;",
- newline,
- string "uw_sqlsuffixString = \"::text\";",
- newline,
- string "uw_sqlsuffixChar = \"::char\";",
- newline,
- string "uw_sqlsuffixBlob = \"::bytea\";",
- newline,
- string "uw_sqlfmtUint4 = \"%u::int4%n\";",
- newline],
- string "}",
- newline,
- newline,
-
- string "static void uw_db_validate(uw_context ctx) {",
+ box [string "static void uw_db_validate(uw_context ctx) {",
newline,
string "PGconn *conn = uw_get_db(ctx);",
newline,
@@ -380,93 +360,111 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
string "}",
newline,
- newline,
-
- string "void uw_db_close(uw_context ctx) {",
- newline,
- string "PQfinish(uw_get_db(ctx));",
- newline,
- string "}",
- newline,
- newline,
-
- string "int uw_db_begin(uw_context ctx) {",
- newline,
- string "PGconn *conn = uw_get_db(ctx);",
- newline,
- string "PGresult *res = PQexec(conn, \"BEGIN ISOLATION LEVEL SERIALIZABLE\");",
- newline,
- newline,
- string "if (res == NULL) return 1;",
- newline,
- newline,
- string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
- box [string "PQclear(res);",
- newline,
- string "return 1;",
- newline],
- string "}",
- newline,
- string "return 0;",
- newline,
- string "}",
- newline,
- newline,
-
- string "int uw_db_commit(uw_context ctx) {",
- newline,
- string "PGconn *conn = uw_get_db(ctx);",
- newline,
- string "PGresult *res = PQexec(conn, \"COMMIT\");",
- newline,
- newline,
- string "if (res == NULL) return 1;",
- newline,
- newline,
- string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
- box [string "PQclear(res);",
- newline,
- string "return 1;",
- newline],
- string "}",
- newline,
- string "return 0;",
- newline,
- string "}",
- newline,
- newline,
-
- string "int uw_db_rollback(uw_context ctx) {",
- newline,
- string "PGconn *conn = uw_get_db(ctx);",
- newline,
- string "PGresult *res = PQexec(conn, \"ROLLBACK\");",
- newline,
- newline,
- string "if (res == NULL) return 1;",
- newline,
- newline,
- string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
- box [string "PQclear(res);",
- newline,
- string "return 1;",
- newline],
- string "}",
- newline,
- string "return 0;",
- newline,
- string "}",
- newline,
newline]
else
box [string "static void uw_db_validate(uw_context ctx) { }",
newline,
string "static void uw_db_prepare(uw_context ctx) { }"],
+ string "static void uw_client_init(void) {",
+ newline,
+ box [string "uw_sqlfmtInt = \"%lld::int8%n\";",
+ newline,
+ string "uw_sqlfmtFloat = \"%g::float8%n\";",
+ newline,
+ string "uw_Estrings = 1;",
+ newline,
+ string "uw_sqlsuffixString = \"::text\";",
+ newline,
+ string "uw_sqlsuffixChar = \"::char\";",
+ newline,
+ string "uw_sqlsuffixBlob = \"::bytea\";",
+ newline,
+ string "uw_sqlfmtUint4 = \"%u::int4%n\";",
+ newline],
+ string "}",
+ newline,
+ newline,
+
+ string "static void uw_db_close(uw_context ctx) {",
+ newline,
+ string "PQfinish(uw_get_db(ctx));",
+ newline,
+ string "}",
+ newline,
+ newline,
+
+ string "static int uw_db_begin(uw_context ctx) {",
+ newline,
+ string "PGconn *conn = uw_get_db(ctx);",
+ newline,
+ string "PGresult *res = PQexec(conn, \"BEGIN ISOLATION LEVEL SERIALIZABLE\");",
+ newline,
+ newline,
+ string "if (res == NULL) return 1;",
+ newline,
+ newline,
+ string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
+ box [string "PQclear(res);",
+ newline,
+ string "return 1;",
+ newline],
+ string "}",
+ newline,
+ string "return 0;",
+ newline,
+ string "}",
+ newline,
+ newline,
+
+ string "static int uw_db_commit(uw_context ctx) {",
+ newline,
+ string "PGconn *conn = uw_get_db(ctx);",
+ newline,
+ string "PGresult *res = PQexec(conn, \"COMMIT\");",
+ newline,
+ newline,
+ string "if (res == NULL) return 1;",
+ newline,
+ newline,
+ string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
+ box [string "PQclear(res);",
+ newline,
+ string "return 1;",
+ newline],
+ string "}",
+ newline,
+ string "return 0;",
+ newline,
+ string "}",
+ newline,
+ newline,
+
+ string "static int uw_db_rollback(uw_context ctx) {",
+ newline,
+ string "PGconn *conn = uw_get_db(ctx);",
+ newline,
+ string "PGresult *res = PQexec(conn, \"ROLLBACK\");",
+ newline,
+ newline,
+ string "if (res == NULL) return 1;",
+ newline,
+ newline,
+ string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
+ box [string "PQclear(res);",
+ newline,
+ string "return 1;",
+ newline],
+ string "}",
+ newline,
+ string "return 0;",
+ newline,
+ string "}",
+
newline,
newline,
- string "void uw_db_init(uw_context ctx) {",
+ string "static void uw_db_init(uw_context ctx) {",
newline,
string "PGconn *conn = PQconnectdb(\"",
string (String.toString dbstring),
diff --git a/src/sqlite.sml b/src/sqlite.sml
index 440c7c28..485e43b4 100644
--- a/src/sqlite.sml
+++ b/src/sqlite.sml
@@ -156,7 +156,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_client_init(void) {",
+ string "static void uw_client_init(void) {",
newline,
box [string "uw_sqlfmtInt = \"%lld%n\";",
newline,
@@ -256,7 +256,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_db_init(uw_context ctx) {",
+ string "static void uw_db_init(uw_context ctx) {",
newline,
string "sqlite3 *sqlite;",
newline,
@@ -283,7 +283,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "void uw_db_close(uw_context ctx) {",
+ string "static void uw_db_close(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -302,7 +302,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "int uw_db_begin(uw_context ctx) {",
+ string "static int uw_db_begin(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -321,7 +321,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
string "}",
newline,
- string "int uw_db_commit(uw_context ctx) {",
+ string "static int uw_db_commit(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,
@@ -341,7 +341,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} =
newline,
newline,
- string "int uw_db_rollback(uw_context ctx) {",
+ string "static int uw_db_rollback(uw_context ctx) {",
newline,
string "uw_conn *conn = uw_get_db(ctx);",
newline,