comparison src/c/urweb.c @ 1369:1a78ca089bd0

Expose buffer type for other C libraries; replace minusSeconds with addSeconds
author Adam Chlipala <adam@chlipala.net>
date Sun, 26 Dec 2010 15:52:56 -0500
parents 8301ee4ab58c
children 44a12a321150
comparison
equal deleted inserted replaced
1368:b2bc8bcd546f 1369:1a78ca089bd0
53 } 53 }
54 54
55 55
56 // Buffers 56 // Buffers
57 57
58 typedef struct { 58 void uw_buffer_init(size_t max, uw_buffer *b, size_t s) {
59 size_t max;
60 char *start, *front, *back;
61 } buf;
62
63 static void buf_init(size_t max, buf *b, size_t s) {
64 b->max = max; 59 b->max = max;
65 b->front = b->start = malloc(s); 60 b->front = b->start = malloc(s);
66 b->back = b->front + s; 61 b->back = b->front + s;
67 } 62 }
68 63
69 static void buf_free(buf *b) { 64 void uw_buffer_free(uw_buffer *b) {
70 free(b->start); 65 free(b->start);
71 } 66 }
72 67
73 static void buf_reset(buf *b) { 68 void uw_buffer_reset(uw_buffer *b) {
74 b->front = b->start; 69 b->front = b->start;
75 } 70 }
76 71
77 static int buf_check(buf *b, size_t extra) { 72 int uw_buffer_check(uw_buffer *b, size_t extra) {
78 if (b->back - b->front < extra) { 73 if (b->back - b->front < extra) {
79 size_t desired = b->front - b->start + extra, next; 74 size_t desired = b->front - b->start + extra, next;
80 char *new_heap; 75 char *new_heap;
81 76
82 next = b->back - b->start; 77 next = b->back - b->start;
100 return 0; 95 return 0;
101 } 96 }
102 97
103 __attribute__((noreturn)) void uw_error(uw_context, failure_kind, const char *, ...); 98 __attribute__((noreturn)) void uw_error(uw_context, failure_kind, const char *, ...);
104 99
105 static void ctx_buf_check(uw_context ctx, const char *kind, buf *b, size_t extra) { 100 static void ctx_uw_buffer_check(uw_context ctx, const char *kind, uw_buffer *b, size_t extra) {
106 if (buf_check(b, extra)) 101 if (uw_buffer_check(b, extra))
107 uw_error(ctx, FATAL, "Memory limit exceeded (%s)", kind); 102 uw_error(ctx, FATAL, "Memory limit exceeded (%s)", kind);
108 } 103 }
109 104
110 static size_t buf_used(buf *b) { 105 size_t uw_buffer_used(uw_buffer *b) {
111 return b->front - b->start; 106 return b->front - b->start;
112 } 107 }
113 108
114 static size_t buf_avail(buf *b) { 109 size_t uw_buffer_avail(uw_buffer *b) {
115 return b->back - b->start; 110 return b->back - b->start;
116 } 111 }
117 112
118 static int buf_append(buf *b, const char *s, size_t len) { 113 int uw_buffer_append(uw_buffer *b, const char *s, size_t len) {
119 if (buf_check(b, len+1)) 114 if (uw_buffer_check(b, len+1))
120 return 1; 115 return 1;
121 116
122 memcpy(b->front, s, len); 117 memcpy(b->front, s, len);
123 b->front += len; 118 b->front += len;
124 *b->front = 0; 119 *b->front = 0;
125 120
126 return 0; 121 return 0;
127 } 122 }
128 123
129 static void ctx_buf_append(uw_context ctx, const char *kind, buf *b, const char *s, size_t len) { 124 static void ctx_uw_buffer_append(uw_context ctx, const char *kind, uw_buffer *b, const char *s, size_t len) {
130 ctx_buf_check(ctx, kind, b, len+1); 125 ctx_uw_buffer_check(ctx, kind, b, len+1);
131 126
132 memcpy(b->front, s, len); 127 memcpy(b->front, s, len);
133 b->front += len; 128 b->front += len;
134 *b->front = 0; 129 *b->front = 0;
135 } 130 }
143 unsigned id; 138 unsigned id;
144 usage mode; 139 usage mode;
145 int pass; 140 int pass;
146 struct client *next; 141 struct client *next;
147 pthread_mutex_t lock, pull_lock; 142 pthread_mutex_t lock, pull_lock;
148 buf msgs; 143 uw_buffer msgs;
149 int sock; 144 int sock;
150 int (*send)(int sockfd, const void *buf, ssize_t len); 145 int (*send)(int sockfd, const void *buf, ssize_t len);
151 int (*close)(int fd); 146 int (*close)(int fd);
152 time_t last_contact; 147 time_t last_contact;
153 unsigned n_channels; 148 unsigned n_channels;
186 clients = realloc(clients, sizeof(client) * n_clients); 181 clients = realloc(clients, sizeof(client) * n_clients);
187 c = malloc(sizeof(client)); 182 c = malloc(sizeof(client));
188 c->id = n_clients-1; 183 c->id = n_clients-1;
189 pthread_mutex_init(&c->lock, NULL); 184 pthread_mutex_init(&c->lock, NULL);
190 pthread_mutex_init(&c->pull_lock, NULL); 185 pthread_mutex_init(&c->pull_lock, NULL);
191 buf_init(uw_messages_max, &c->msgs, 0); 186 uw_buffer_init(uw_messages_max, &c->msgs, 0);
192 clients[n_clients-1] = c; 187 clients[n_clients-1] = c;
193 } 188 }
194 189
195 pthread_mutex_lock(&c->lock); 190 pthread_mutex_lock(&c->lock);
196 c->mode = USED; 191 c->mode = USED;
197 c->pass = rand(); 192 c->pass = rand();
198 c->sock = -1; 193 c->sock = -1;
199 c->last_contact = time(NULL); 194 c->last_contact = time(NULL);
200 buf_reset(&c->msgs); 195 uw_buffer_reset(&c->msgs);
201 c->n_channels = 0; 196 c->n_channels = 0;
202 c->refcount = 0; 197 c->refcount = 0;
203 c->data = uw_init_client_data(); 198 c->data = uw_init_client_data();
204 pthread_mutex_unlock(&c->lock); 199 pthread_mutex_unlock(&c->lock);
205 200
284 c->sock = -1; 279 c->sock = -1;
285 } 280 }
286 281
287 c->last_contact = time(NULL); 282 c->last_contact = time(NULL);
288 283
289 if (buf_used(&c->msgs) > 0) { 284 if (uw_buffer_used(&c->msgs) > 0) {
290 send(sock, on_success, strlen(on_success)); 285 send(sock, on_success, strlen(on_success));
291 send(sock, begin_msgs, sizeof(begin_msgs) - 1); 286 send(sock, begin_msgs, sizeof(begin_msgs) - 1);
292 send(sock, c->msgs.start, buf_used(&c->msgs)); 287 send(sock, c->msgs.start, uw_buffer_used(&c->msgs));
293 buf_reset(&c->msgs); 288 uw_buffer_reset(&c->msgs);
294 close(sock); 289 close(sock);
295 } 290 }
296 else { 291 else {
297 c->sock = sock; 292 c->sock = sock;
298 c->send = send; 293 c->send = send;
313 static uw_Basis_channel new_channel(client *c) { 308 static uw_Basis_channel new_channel(client *c) {
314 uw_Basis_channel ch = {c->id, c->n_channels++}; 309 uw_Basis_channel ch = {c->id, c->n_channels++};
315 return ch; 310 return ch;
316 } 311 }
317 312
318 static void client_send(client *c, buf *msg) { 313 static void client_send(client *c, uw_buffer *msg) {
319 pthread_mutex_lock(&c->lock); 314 pthread_mutex_lock(&c->lock);
320 315
321 if (c->sock != -1) { 316 if (c->sock != -1) {
322 c->send(c->sock, on_success, strlen(on_success)); 317 c->send(c->sock, on_success, strlen(on_success));
323 c->send(c->sock, begin_msgs, sizeof(begin_msgs) - 1); 318 c->send(c->sock, begin_msgs, sizeof(begin_msgs) - 1);
324 c->send(c->sock, msg->start, buf_used(msg)); 319 c->send(c->sock, msg->start, uw_buffer_used(msg));
325 c->close(c->sock); 320 c->close(c->sock);
326 c->sock = -1; 321 c->sock = -1;
327 } else if (buf_append(&c->msgs, msg->start, buf_used(msg))) 322 } else if (uw_buffer_append(&c->msgs, msg->start, uw_buffer_used(msg)))
328 fprintf(stderr, "Client message buffer size exceeded"); 323 fprintf(stderr, "Client message buffer size exceeded");
329 324
330 pthread_mutex_unlock(&c->lock); 325 pthread_mutex_unlock(&c->lock);
331 } 326 }
332 327
363 void *arg; 358 void *arg;
364 } cleanup; 359 } cleanup;
365 360
366 typedef struct { 361 typedef struct {
367 unsigned client; 362 unsigned client;
368 buf msgs; 363 uw_buffer msgs;
369 } delta; 364 } delta;
370 365
371 typedef enum { 366 typedef enum {
372 UNSET, NORMAL, FIL, SUBFORM, SUBFORMS, ENTRY 367 UNSET, NORMAL, FIL, SUBFORM, SUBFORMS, ENTRY
373 } input_kind; 368 } input_kind;
405 uw_app *app; 400 uw_app *app;
406 401
407 char *(*get_header)(void *, const char *); 402 char *(*get_header)(void *, const char *);
408 void *get_header_data; 403 void *get_header_data;
409 404
410 buf outHeaders, page, heap, script; 405 uw_buffer outHeaders, page, heap, script;
411 int returning_indirectly; 406 int returning_indirectly;
412 input *inputs, *subinputs, *cur_container; 407 input *inputs, *subinputs, *cur_container;
413 size_t sz_inputs, n_subinputs, used_subinputs; 408 size_t sz_inputs, n_subinputs, used_subinputs;
414 409
415 int source_count; 410 int source_count;
463 ctx->app = NULL; 458 ctx->app = NULL;
464 459
465 ctx->get_header = NULL; 460 ctx->get_header = NULL;
466 ctx->get_header_data = NULL; 461 ctx->get_header_data = NULL;
467 462
468 buf_init(uw_headers_max, &ctx->outHeaders, 0); 463 uw_buffer_init(uw_headers_max, &ctx->outHeaders, 0);
469 buf_init(uw_page_max, &ctx->page, 0); 464 uw_buffer_init(uw_page_max, &ctx->page, 0);
470 ctx->returning_indirectly = 0; 465 ctx->returning_indirectly = 0;
471 buf_init(uw_heap_max, &ctx->heap, uw_min_heap); 466 uw_buffer_init(uw_heap_max, &ctx->heap, uw_min_heap);
472 buf_init(uw_script_max, &ctx->script, 1); 467 uw_buffer_init(uw_script_max, &ctx->script, 1);
473 ctx->script.start[0] = 0; 468 ctx->script.start[0] = 0;
474 469
475 ctx->inputs = malloc(0); 470 ctx->inputs = malloc(0);
476 ctx->cur_container = NULL; 471 ctx->cur_container = NULL;
477 ctx->subinputs = malloc(0); 472 ctx->subinputs = malloc(0);
550 } 545 }
551 546
552 void uw_free(uw_context ctx) { 547 void uw_free(uw_context ctx) {
553 size_t i; 548 size_t i;
554 549
555 buf_free(&ctx->outHeaders); 550 uw_buffer_free(&ctx->outHeaders);
556 buf_free(&ctx->script); 551 uw_buffer_free(&ctx->script);
557 buf_free(&ctx->page); 552 uw_buffer_free(&ctx->page);
558 buf_free(&ctx->heap); 553 uw_buffer_free(&ctx->heap);
559 free(ctx->inputs); 554 free(ctx->inputs);
560 free(ctx->subinputs); 555 free(ctx->subinputs);
561 free(ctx->cleanup); 556 free(ctx->cleanup);
562 free(ctx->transactionals); 557 free(ctx->transactionals);
563 uw_free_client_data(ctx->client_data); 558 uw_free_client_data(ctx->client_data);
564 559
565 for (i = 0; i < ctx->n_deltas; ++i) 560 for (i = 0; i < ctx->n_deltas; ++i)
566 buf_free(&ctx->deltas[i].msgs); 561 uw_buffer_free(&ctx->deltas[i].msgs);
567 free(ctx->deltas); 562 free(ctx->deltas);
568 563
569 for (i = 0; i < ctx->n_globals; ++i) 564 for (i = 0; i < ctx->n_globals; ++i)
570 if (ctx->globals[i].free) 565 if (ctx->globals[i].free)
571 ctx->globals[i].free(ctx->globals[i].data); 566 ctx->globals[i].free(ctx->globals[i].data);
573 568
574 free(ctx); 569 free(ctx);
575 } 570 }
576 571
577 void uw_reset_keep_error_message(uw_context ctx) { 572 void uw_reset_keep_error_message(uw_context ctx) {
578 buf_reset(&ctx->outHeaders); 573 uw_buffer_reset(&ctx->outHeaders);
579 buf_reset(&ctx->script); 574 uw_buffer_reset(&ctx->script);
580 ctx->script.start[0] = 0; 575 ctx->script.start[0] = 0;
581 buf_reset(&ctx->page); 576 uw_buffer_reset(&ctx->page);
582 ctx->returning_indirectly = 0; 577 ctx->returning_indirectly = 0;
583 buf_reset(&ctx->heap); 578 uw_buffer_reset(&ctx->heap);
584 ctx->regions = NULL; 579 ctx->regions = NULL;
585 ctx->cleanup_front = ctx->cleanup; 580 ctx->cleanup_front = ctx->cleanup;
586 ctx->source_count = 0; 581 ctx->source_count = 0;
587 ctx->used_deltas = 0; 582 ctx->used_deltas = 0;
588 ctx->client = NULL; 583 ctx->client = NULL;
1155 void uw_set_needs_sig(uw_context ctx, int n) { 1150 void uw_set_needs_sig(uw_context ctx, int n) {
1156 ctx->needs_sig = n; 1151 ctx->needs_sig = n;
1157 } 1152 }
1158 1153
1159 1154
1160 static void buf_check_ctx(uw_context ctx, const char *kind, buf *b, size_t extra, const char *desc) { 1155 static void uw_buffer_check_ctx(uw_context ctx, const char *kind, uw_buffer *b, size_t extra, const char *desc) {
1161 if (b->back - b->front < extra) { 1156 if (b->back - b->front < extra) {
1162 size_t desired = b->front - b->start + extra, next; 1157 size_t desired = b->front - b->start + extra, next;
1163 char *new_heap; 1158 char *new_heap;
1164 1159
1165 next = b->back - b->start; 1160 next = b->back - b->start;
1186 b->start = new_heap; 1181 b->start = new_heap;
1187 } 1182 }
1188 } 1183 }
1189 1184
1190 void uw_check_heap(uw_context ctx, size_t extra) { 1185 void uw_check_heap(uw_context ctx, size_t extra) {
1191 buf_check_ctx(ctx, "heap", &ctx->heap, extra, "heap chunk"); 1186 uw_buffer_check_ctx(ctx, "heap", &ctx->heap, extra, "heap chunk");
1192 } 1187 }
1193 1188
1194 char *uw_heap_front(uw_context ctx) { 1189 char *uw_heap_front(uw_context ctx) {
1195 return ctx->heap.front; 1190 return ctx->heap.front;
1196 } 1191 }
1229 ctx->heap.front = (char *) r; 1224 ctx->heap.front = (char *) r;
1230 ctx->regions = r->next; 1225 ctx->regions = r->next;
1231 } 1226 }
1232 1227
1233 void uw_memstats(uw_context ctx) { 1228 void uw_memstats(uw_context ctx) {
1234 printf("Headers: %lu/%lu\n", (unsigned long)buf_used(&ctx->outHeaders), (unsigned long)buf_avail(&ctx->outHeaders)); 1229 printf("Headers: %lu/%lu\n", (unsigned long)uw_buffer_used(&ctx->outHeaders), (unsigned long)uw_buffer_avail(&ctx->outHeaders));
1235 printf("Script: %lu/%lu\n", (unsigned long)buf_used(&ctx->script), (unsigned long)buf_avail(&ctx->script)); 1230 printf("Script: %lu/%lu\n", (unsigned long)uw_buffer_used(&ctx->script), (unsigned long)uw_buffer_avail(&ctx->script));
1236 printf("Page: %lu/%lu\n", (unsigned long)buf_used(&ctx->page), (unsigned long)buf_avail(&ctx->page)); 1231 printf("Page: %lu/%lu\n", (unsigned long)uw_buffer_used(&ctx->page), (unsigned long)uw_buffer_avail(&ctx->page));
1237 printf("Heap: %lu/%lu\n", (unsigned long)buf_used(&ctx->heap), (unsigned long)buf_avail(&ctx->heap)); 1232 printf("Heap: %lu/%lu\n", (unsigned long)uw_buffer_used(&ctx->heap), (unsigned long)uw_buffer_avail(&ctx->heap));
1238 } 1233 }
1239 1234
1240 int uw_send(uw_context ctx, int sock) { 1235 int uw_send(uw_context ctx, int sock) {
1241 int n = uw_really_send(sock, ctx->outHeaders.start, ctx->outHeaders.front - ctx->outHeaders.start); 1236 int n = uw_really_send(sock, ctx->outHeaders.start, ctx->outHeaders.front - ctx->outHeaders.start);
1242 1237
1278 1273
1279 return output(data, ctx->page.start, ctx->page.front - ctx->page.start); 1274 return output(data, ctx->page.start, ctx->page.front - ctx->page.start);
1280 } 1275 }
1281 1276
1282 static void uw_check_headers(uw_context ctx, size_t extra) { 1277 static void uw_check_headers(uw_context ctx, size_t extra) {
1283 ctx_buf_check(ctx, "headers", &ctx->outHeaders, extra); 1278 ctx_uw_buffer_check(ctx, "headers", &ctx->outHeaders, extra);
1284 } 1279 }
1285 1280
1286 void uw_write_header(uw_context ctx, uw_Basis_string s) { 1281 void uw_write_header(uw_context ctx, uw_Basis_string s) {
1287 int len = strlen(s); 1282 int len = strlen(s);
1288 1283
1290 strcpy(ctx->outHeaders.front, s); 1285 strcpy(ctx->outHeaders.front, s);
1291 ctx->outHeaders.front += len; 1286 ctx->outHeaders.front += len;
1292 } 1287 }
1293 1288
1294 void uw_clear_headers(uw_context ctx) { 1289 void uw_clear_headers(uw_context ctx) {
1295 buf_reset(&ctx->outHeaders); 1290 uw_buffer_reset(&ctx->outHeaders);
1296 } 1291 }
1297 1292
1298 static void uw_check_script(uw_context ctx, size_t extra) { 1293 static void uw_check_script(uw_context ctx, size_t extra) {
1299 ctx_buf_check(ctx, "script", &ctx->script, extra); 1294 ctx_uw_buffer_check(ctx, "script", &ctx->script, extra);
1300 } 1295 }
1301 1296
1302 void uw_write_script(uw_context ctx, uw_Basis_string s) { 1297 void uw_write_script(uw_context ctx, uw_Basis_string s) {
1303 int len = strlen(s); 1298 int len = strlen(s);
1304 1299
1511 1506
1512 return uw_unit_v; 1507 return uw_unit_v;
1513 } 1508 }
1514 1509
1515 static void uw_check(uw_context ctx, size_t extra) { 1510 static void uw_check(uw_context ctx, size_t extra) {
1516 ctx_buf_check(ctx, "page", &ctx->page, extra); 1511 ctx_uw_buffer_check(ctx, "page", &ctx->page, extra);
1517 } 1512 }
1518 1513
1519 static void uw_writec_unsafe(uw_context ctx, char c) { 1514 static void uw_writec_unsafe(uw_context ctx, char c) {
1520 *(ctx->page.front)++ = c; 1515 *(ctx->page.front)++ = c;
1521 } 1516 }
3001 if (ctx->used_deltas >= ctx->n_deltas) { 2996 if (ctx->used_deltas >= ctx->n_deltas) {
3002 if (ctx->n_deltas + 1 > uw_deltas_max) 2997 if (ctx->n_deltas + 1 > uw_deltas_max)
3003 uw_error(ctx, FATAL, "Exceeded limit on number of deltas"); 2998 uw_error(ctx, FATAL, "Exceeded limit on number of deltas");
3004 2999
3005 ctx->deltas = realloc(ctx->deltas, sizeof(delta) * ++ctx->n_deltas); 3000 ctx->deltas = realloc(ctx->deltas, sizeof(delta) * ++ctx->n_deltas);
3006 buf_init(uw_messages_max, &ctx->deltas[ctx->n_deltas-1].msgs, 0); 3001 uw_buffer_init(uw_messages_max, &ctx->deltas[ctx->n_deltas-1].msgs, 0);
3007 } 3002 }
3008 3003
3009 d = &ctx->deltas[ctx->used_deltas++]; 3004 d = &ctx->deltas[ctx->used_deltas++];
3010 d->client = client; 3005 d->client = client;
3011 buf_reset(&d->msgs); 3006 uw_buffer_reset(&d->msgs);
3012 return d; 3007 return d;
3013 } 3008 }
3014 3009
3015 uw_Basis_channel uw_Basis_new_channel(uw_context ctx, uw_unit u) { 3010 uw_Basis_channel uw_Basis_new_channel(uw_context ctx, uw_unit u) {
3016 if (ctx->client == NULL) 3011 if (ctx->client == NULL)
3027 3022
3028 len = strlen(msg); 3023 len = strlen(msg);
3029 3024
3030 sprintf(pre, "%u\n%n", chn.chn, &preLen); 3025 sprintf(pre, "%u\n%n", chn.chn, &preLen);
3031 3026
3032 ctx_buf_append(ctx, "messages", &d->msgs, pre, preLen); 3027 ctx_uw_buffer_append(ctx, "messages", &d->msgs, pre, preLen);
3033 ctx_buf_append(ctx, "messages", &d->msgs, msg, len); 3028 ctx_uw_buffer_append(ctx, "messages", &d->msgs, msg, len);
3034 ctx_buf_append(ctx, "messages", &d->msgs, "\n", 1); 3029 ctx_uw_buffer_append(ctx, "messages", &d->msgs, "\n", 1);
3035 3030
3036 return uw_unit_v; 3031 return uw_unit_v;
3037 } 3032 }
3038 3033
3039 int uw_rollback(uw_context ctx, int will_retry) { 3034 int uw_rollback(uw_context ctx, int will_retry) {
3110 3105
3111 // Splice script data into appropriate part of page 3106 // Splice script data into appropriate part of page
3112 if (ctx->returning_indirectly || ctx->script_header[0] == 0) { 3107 if (ctx->returning_indirectly || ctx->script_header[0] == 0) {
3113 char *start = strstr(ctx->page.start, "<sc>"); 3108 char *start = strstr(ctx->page.start, "<sc>");
3114 if (start) { 3109 if (start) {
3115 memmove(start, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 4); 3110 memmove(start, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 4);
3116 ctx->page.front -= 4; 3111 ctx->page.front -= 4;
3117 } 3112 }
3118 } else if (buf_used(&ctx->script) == 0) { 3113 } else if (uw_buffer_used(&ctx->script) == 0) {
3119 size_t len = strlen(ctx->script_header); 3114 size_t len = strlen(ctx->script_header);
3120 char *start = strstr(ctx->page.start, "<sc>"); 3115 char *start = strstr(ctx->page.start, "<sc>");
3121 if (start) { 3116 if (start) {
3122 ctx_buf_check(ctx, "page", &ctx->page, buf_used(&ctx->page) - 4 + len); 3117 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) - 4 + len);
3123 start = strstr(ctx->page.start, "<sc>"); 3118 start = strstr(ctx->page.start, "<sc>");
3124 memmove(start + len, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 3); 3119 memmove(start + len, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 3);
3125 ctx->page.front += len - 4; 3120 ctx->page.front += len - 4;
3126 memcpy(start, ctx->script_header, len); 3121 memcpy(start, ctx->script_header, len);
3127 } 3122 }
3128 } else { 3123 } else {
3129 size_t lenH = strlen(ctx->script_header), len = buf_used(&ctx->script); 3124 size_t lenH = strlen(ctx->script_header), len = uw_buffer_used(&ctx->script);
3130 size_t lenP = lenH + 40 + len; 3125 size_t lenP = lenH + 40 + len;
3131 char *start = strstr(ctx->page.start, "<sc>"); 3126 char *start = strstr(ctx->page.start, "<sc>");
3132 if (start) { 3127 if (start) {
3133 ctx_buf_check(ctx, "page", &ctx->page, buf_used(&ctx->page) - 4 + lenP); 3128 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->page) - 4 + lenP);
3134 start = strstr(ctx->page.start, "<sc>"); 3129 start = strstr(ctx->page.start, "<sc>");
3135 memmove(start + lenP, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 3); 3130 memmove(start + lenP, start + 4, uw_buffer_used(&ctx->page) - (start - ctx->page.start) - 3);
3136 ctx->page.front += lenP - 4; 3131 ctx->page.front += lenP - 4;
3137 memcpy(start, ctx->script_header, lenH); 3132 memcpy(start, ctx->script_header, lenH);
3138 memcpy(start + lenH, "<script type=\"text/javascript\">", 31); 3133 memcpy(start + lenH, "<script type=\"text/javascript\">", 31);
3139 memcpy(start + lenH + 31, ctx->script.start, len); 3134 memcpy(start + lenH + 31, ctx->script.start, len);
3140 memcpy(start + lenH + 31 + len, "</script>", 9); 3135 memcpy(start + lenH + 31 + len, "</script>", 9);
3336 __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, uw_Basis_string mimeType) { 3331 __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, uw_Basis_string mimeType) {
3337 cleanup *cl; 3332 cleanup *cl;
3338 int len; 3333 int len;
3339 3334
3340 ctx->returning_indirectly = 1; 3335 ctx->returning_indirectly = 1;
3341 buf_reset(&ctx->outHeaders); 3336 uw_buffer_reset(&ctx->outHeaders);
3342 buf_reset(&ctx->page); 3337 uw_buffer_reset(&ctx->page);
3343 3338
3344 uw_write_header(ctx, on_success); 3339 uw_write_header(ctx, on_success);
3345 uw_write_header(ctx, "Content-Type: "); 3340 uw_write_header(ctx, "Content-Type: ");
3346 uw_write_header(ctx, mimeType); 3341 uw_write_header(ctx, mimeType);
3347 uw_write_header(ctx, "\r\nContent-Length: "); 3342 uw_write_header(ctx, "\r\nContent-Length: ");
3348 ctx_buf_check(ctx, "headers", &ctx->outHeaders, INTS_MAX); 3343 ctx_uw_buffer_check(ctx, "headers", &ctx->outHeaders, INTS_MAX);
3349 sprintf(ctx->outHeaders.front, "%lu%n", (unsigned long)b.size, &len); 3344 sprintf(ctx->outHeaders.front, "%lu%n", (unsigned long)b.size, &len);
3350 ctx->outHeaders.front += len; 3345 ctx->outHeaders.front += len;
3351 uw_write_header(ctx, "\r\n"); 3346 uw_write_header(ctx, "\r\n");
3352 3347
3353 ctx_buf_append(ctx, "page", &ctx->page, b.data, b.size); 3348 ctx_uw_buffer_append(ctx, "page", &ctx->page, b.data, b.size);
3354 3349
3355 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) 3350 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
3356 cl->func(cl->arg); 3351 cl->func(cl->arg);
3357 3352
3358 ctx->cleanup_front = ctx->cleanup; 3353 ctx->cleanup_front = ctx->cleanup;
3363 __attribute__((noreturn)) void uw_redirect(uw_context ctx, uw_Basis_string url) { 3358 __attribute__((noreturn)) void uw_redirect(uw_context ctx, uw_Basis_string url) {
3364 cleanup *cl; 3359 cleanup *cl;
3365 char *s; 3360 char *s;
3366 3361
3367 ctx->returning_indirectly = 1; 3362 ctx->returning_indirectly = 1;
3368 buf_reset(&ctx->page); 3363 uw_buffer_reset(&ctx->page);
3369 ctx_buf_check(ctx, "page", &ctx->page, buf_used(&ctx->outHeaders)+1); 3364 ctx_uw_buffer_check(ctx, "page", &ctx->page, uw_buffer_used(&ctx->outHeaders)+1);
3370 memcpy(ctx->page.start, ctx->outHeaders.start, buf_used(&ctx->outHeaders)); 3365 memcpy(ctx->page.start, ctx->outHeaders.start, uw_buffer_used(&ctx->outHeaders));
3371 ctx->page.start[buf_used(&ctx->outHeaders)] = 0; 3366 ctx->page.start[uw_buffer_used(&ctx->outHeaders)] = 0;
3372 buf_reset(&ctx->outHeaders); 3367 uw_buffer_reset(&ctx->outHeaders);
3373 3368
3374 uw_write_header(ctx, on_redirect); 3369 uw_write_header(ctx, on_redirect);
3375 3370
3376 s = strchr(ctx->page.start, '\n'); 3371 s = strchr(ctx->page.start, '\n');
3377 if (s) { 3372 if (s) {
3457 uw_Basis_time uw_Basis_now(uw_context ctx) { 3452 uw_Basis_time uw_Basis_now(uw_context ctx) {
3458 uw_Basis_time r = { time(NULL) }; 3453 uw_Basis_time r = { time(NULL) };
3459 return r; 3454 return r;
3460 } 3455 }
3461 3456
3462 uw_Basis_time uw_Basis_minusSeconds(uw_context ctx, uw_Basis_time tm, uw_Basis_int n) { 3457 uw_Basis_time uw_Basis_addSeconds(uw_context ctx, uw_Basis_time tm, uw_Basis_int n) {
3463 tm.seconds -= n; 3458 tm.seconds += n;
3464 return tm; 3459 return tm;
3465 } 3460 }
3466 3461
3467 void *uw_get_global(uw_context ctx, char *name) { 3462 void *uw_get_global(uw_context ctx, char *name) {
3468 int i; 3463 int i;