2 ashd - A Sane HTTP Daemon
3 Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31 static int base64rev[] = {
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
35 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
36 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
37 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
38 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
39 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
45 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
50 void _sizebuf(struct buffer *buf, size_t wanted, size_t el)
62 buf->b = srealloc(buf->b, n * el);
64 buf->b = smalloc(n * el);
68 char *decstr(char **p, size_t *len)
72 for(p2 = *p; (p2 - *p) < *len; p2++) {
85 char *vsprintf2(char *format, va_list al)
92 ret = vsnprintf(NULL, 0, format, al2);
94 buf = smalloc(ret + 1);
96 vsnprintf(buf, ret + 1, format, al2);
101 char *sprintf2(char *format, ...)
106 va_start(args, format);
107 buf = vsprintf2(format, args);
112 char *sprintf3(char *format, ...)
114 static char *buf = NULL;
119 va_start(args, format);
120 buf = vsprintf2(format, args);
127 return((off_t)strtoll(n, NULL, 10));
130 char **tokenize(char *src)
155 else if(isspace(*p) || !*p)
163 n = memcpy(malloc(cl + 1), p2, cl);
165 for(p2 = n; *p2; cl--) {
167 memmove(p2, p2 + 1, cl--);
169 } else if(*p2 == '\"') {
170 memmove(p2, p2 + 1, cl);
175 ret = realloc(ret, sizeof(char *) * (++s));
178 ret = realloc(ret, sizeof(char *) * (++s));
183 void freeca(char **ca)
198 for(i = 0; *a; a++, i++);
202 void bvprintf(struct charbuf *buf, char *format, va_list al)
209 ret = vsnprintf(buf->b + buf->d, buf->s - buf->d, format, al2);
211 if(ret < buf->s - buf->d) {
215 sizebuf(*buf, buf->d + ret + 1);
219 void bprintf(struct charbuf *buf, char *format, ...)
223 va_start(args, format);
224 bvprintf(buf, format, args);
228 void replstr(char **p, char *n)
241 char *base64encode(char *data, size_t datalen)
250 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
251 bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
252 bufadd(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]);
253 bufadd(buf, base64set[data[2] & 0x3f]);
259 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
260 bufadd(buf, base64set[(data[0] & 0x03) << 4]);
261 bufcat(buf, "==", 2);
265 bufadd(buf, base64set[(data[0] & 0xfc) >> 2]);
266 bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
267 bufadd(buf, base64set[(data[1] & 0x0f) << 2]);
274 char *base64decode(char *data, size_t *datalen)
283 for(; *data > 0; data++)
285 c = (int)(unsigned char)*data;
290 if(base64rev[c] == -1)
298 cur |= base64rev[c] >> -b;
303 cur |= base64rev[c] << b;
313 if((c >= '0') && (c <= '9')) return(c - '0');
314 else if((c >= 'a') && (c <= 'f')) return(c - 'a' + 10);
315 else if((c >= 'A') && (c <= 'F')) return(c - 'A' + 10);
319 static int btheight(struct btree *tree)
326 static void btsetheight(struct btree *tree)
330 tree->h = max(btheight(tree->l), btheight(tree->r)) + 1;
333 static void bbtrl(struct btree **tree);
335 static void bbtrr(struct btree **tree)
337 struct btree *m, *l, *r;
339 if(btheight((*tree)->l->r) > btheight((*tree)->l->l))
351 static void bbtrl(struct btree **tree)
353 struct btree *m, *l, *r;
355 if(btheight((*tree)->r->l) > btheight((*tree)->r->r))
367 static int ptrcmp(void *a, void *b)
376 int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *))
379 struct btree *s, **sp, *o;
385 if((c = cmp(item, (*tree)->d)) < 0) {
386 r = bbtreedel(&(*tree)->l, item, cmp);
388 r = bbtreedel(&(*tree)->r, item, cmp);
392 if(((*tree)->r != NULL) && ((*tree)->l != NULL)) {
395 while(s->l != NULL) {
403 } else if((*tree)->l != NULL) {
405 } else if((*tree)->r != NULL) {
414 if(btheight((*tree)->l) > btheight((*tree)->r) + 1)
416 if(btheight((*tree)->r) > btheight((*tree)->l) + 1)
422 void freebtree(struct btree **tree, void (*ffunc)(void *))
426 freebtree(&(*tree)->l, ffunc);
427 freebtree(&(*tree)->r, ffunc);
434 int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *))
441 *tree = szmalloc(sizeof(**tree));
446 if((c = cmp(item, (*tree)->d)) < 0)
447 r = bbtreeput(&(*tree)->l, item, cmp);
449 r = bbtreeput(&(*tree)->r, item, cmp);
453 if(btheight((*tree)->l) > btheight((*tree)->r) + 1)
455 if(btheight((*tree)->r) > btheight((*tree)->l) + 1)
460 void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *))
469 c = cmp(key, tree->d);
480 ssize_t (*read)(void *pdata, void *buf, size_t len);
481 ssize_t (*write)(void *pdata, const void *buf, size_t len);
482 off_t (*seek)(void *pdata, off_t offset, int whence);
483 int (*close)(void *pdata);
487 #if defined(HAVE_GLIBC_STDIO)
488 static ssize_t wrapread(void *pdata, char *buf, size_t len)
490 struct stdif *nf = pdata;
492 return(nf->read(nf->pdata, buf, len));
495 static ssize_t wrapwrite(void *pdata, const char *buf, size_t len)
497 struct stdif *nf = pdata;
502 * XXX? In seeming violation of its own manual, glibc requires the
503 * cookie-write function to complete writing the entire buffer,
504 * rather than working like write(2).
508 ret = nf->write(nf->pdata, buf + off, len - off);
516 static int wrapseek(void *pdata, off_t *pos, int whence)
518 struct stdif *nf = pdata;
521 ret = nf->seek(nf->pdata, *pos, whence);
528 static int wrapclose(void *pdata)
530 struct stdif *nf = pdata;
533 if(nf->close != NULL)
534 ret = nf->close(nf->pdata);
541 FILE *funstdio(void *pdata,
542 ssize_t (*read)(void *pdata, void *buf, size_t len),
543 ssize_t (*write)(void *pdata, const void *buf, size_t len),
544 off_t (*seek)(void *pdata, off_t offset, int whence),
545 int (*close)(void *pdata))
548 cookie_io_functions_t io;
562 *nf = (struct stdif){.read = read, .write = write, .seek = seek, .close = close, .pdata = pdata};
563 io = (cookie_io_functions_t) {
564 .read = read?wrapread:NULL,
565 .write = write?wrapwrite:NULL,
566 .seek = seek?wrapseek:NULL,
569 return(fopencookie(nf, mode, io));
571 #elif defined(HAVE_BSD_STDIO)
572 static int wrapread(void *pdata, char *buf, int len)
574 struct stdif *nf = pdata;
576 return(nf->read(nf->pdata, buf, len));
579 static int wrapwrite(void *pdata, const char *buf, int len)
581 struct stdif *nf = pdata;
583 return(nf->write(nf->pdata, buf, len));
586 static fpos_t wrapseek(void *pdata, fpos_t pos, int whence)
588 struct stdif *nf = pdata;
590 return(nf->seek(nf->pdata, pos, whence));
593 static int wrapclose(void *pdata)
595 struct stdif *nf = pdata;
598 if(nf->close != NULL)
599 ret = nf->close(nf->pdata);
606 FILE *funstdio(void *pdata,
607 ssize_t (*read)(void *pdata, void *buf, size_t len),
608 ssize_t (*write)(void *pdata, const void *buf, size_t len),
609 off_t (*seek)(void *pdata, off_t offset, int whence),
610 int (*close)(void *pdata))
615 *nf = (struct stdif){.read = read, .write = write, .seek = seek, .close = close, .pdata = pdata};
616 return(funopen(nf, read?wrapread:NULL, write?wrapwrite:NULL, seek?wrapseek:NULL, wrapclose));
619 #error "No stdio implementation for this system"