2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2004 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 2 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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <netinet/in.h>
48 static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
49 static int base64rev[] = {
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
53 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
54 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
55 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
56 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
57 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 static char *base32set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
68 static int base32rev[] = {
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
74 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
75 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
76 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
77 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
78 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
79 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
80 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
81 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
82 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
83 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
84 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
87 char *vsprintf2(char *format, va_list al)
94 ret = vsnprintf(NULL, 0, format, al2);
96 if((buf = malloc(ret + 1)) == NULL)
102 vsnprintf(buf, ret + 1, format, al2);
107 char *sprintf2(char *format, ...)
112 va_start(args, format);
113 buf = vsprintf2(format, args);
118 wchar_t *vswprintf2(wchar_t *format, va_list al)
125 buf = smalloc(sizeof(wchar_t) * (bufsize = 1024));
129 ret = vswprintf(buf, bufsize, format, al2);
133 buf = srealloc(buf, sizeof(wchar_t) * (bufsize *= 2));
135 if(bufsize > ret + 1)
136 buf = srealloc(buf, sizeof(wchar_t) * (ret + 1));
140 wchar_t *swprintf2(wchar_t *format, ...)
145 va_start(args, format);
146 buf = vswprintf2(format, args);
151 int havecharset(char *charset)
155 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
158 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
164 wchar_t *icmbstowcs(char *mbs, char *charset)
169 size_t len1, len2, bufsize, data;
172 len1 = strlen(mbs) + 1;
173 bufsize = len2 = len1 * sizeof(wchar_t);
174 if((buf = malloc(bufsize)) == NULL)
180 charset = nl_langinfo(CODESET);
181 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
184 flog(LOG_ERR, "icmbstowcs: could not open iconv structure for %s: %s", charset, strerror(errno));
192 ret = iconv(cd, &mbs, &len1, &p, &len2);
200 if((p2 = realloc(buf, bufsize)) == NULL)
217 buf = realloc(buf, p - buf);
219 return((wchar_t *)buf);
222 wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def)
224 static wchar_t *buf = NULL;
228 if((buf = icmbstowcs(mbs, charset)) == NULL)
230 if((def != NULL) && (*def == L'~'))
233 flog(LOG_WARNING, "icsmbstowcs: could not convert wcs string into charset %s: %s", charset, strerror(errno));
242 char *icwcstombs(wchar_t *wcs, char *charset)
247 size_t len1, len2, bufsize, data;
250 len1 = sizeof(wchar_t) * (wcslen(wcs) + 1);
251 bufsize = len2 = len1;
252 if((buf = malloc(bufsize)) == NULL)
260 charset = nl_langinfo(CODESET);
261 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
264 flog(LOG_ERR, "icwcstombs: could not open iconv structure for %s: %s", charset, strerror(errno));
272 ret = iconv(cd, (char **)&wcs, &len1, &p, &len2);
280 if((p2 = realloc(buf, bufsize)) == NULL)
297 buf = realloc(buf, p - buf);
302 char *icswcstombs(wchar_t *wcs, char *charset, char *def)
304 static char *buf = NULL;
308 if((buf = icwcstombs(wcs, charset)) == NULL)
310 if((def != NULL) && (*def == '~'))
313 flog(LOG_WARNING, "icswcstombs: could not convert mbs string from charset %s: %s", charset, strerror(errno));
322 wchar_t *wcstolower(wchar_t *wcs)
326 for(p = wcs; *p != L'\0'; p++)
331 wchar_t ucptowc(int ucp)
334 unsigned long ucpbuf;
338 size_t len1, len2, bufsize, data;
342 mbsp = (char *)&ucpbuf;
344 bufsize = len2 = len1 * sizeof(wchar_t);
345 if((buf = malloc(bufsize)) == NULL)
350 if((cd = iconv_open("wchar_t", "UCS-4BE")) == (iconv_t)-1)
353 flog(LOG_ERR, "ucptowc: could not open iconv structure for UCS-4BE: %s", strerror(errno));
361 ret = iconv(cd, &mbsp, &len1, &p, &len2);
369 if((p2 = realloc(buf, bufsize)) == NULL)
386 buf = realloc(buf, p - buf);
388 res = *(wchar_t *)buf;
393 void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo)
395 if(*bufsize >= reqsize)
400 *buf = srealloc(*buf, elsize * ((*bufsize) = reqsize));
405 while(*bufsize < reqsize)
407 *buf = srealloc(*buf, elsize * (*bufsize));
416 gettimeofday(&tv, NULL);
417 return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
420 wchar_t *wcslower(wchar_t *wcs)
424 for(p = wcs; *p != L'\0'; p++)
429 #ifndef HAVE_WCSCASECMP
430 int wcscasecmp(const wchar_t *s1, const wchar_t *s2)
432 for(; (towlower(*s1) == towlower(*s2)) && (*s1 != L'\0'); s1++, s2++);
433 return(towlower(*s1) - towlower(*s2));
437 char *hexencode(char *data, size_t datalen)
440 size_t bufsize, bufdata;
444 bufsize = bufdata = 0;
445 for(; datalen > 0; datalen--, data++)
447 dig = (*data & 0xF0) >> 4;
449 this = 'A' + dig - 10;
455 this = 'A' + dig - 10;
464 char *hexdecode(char *data, size_t *len)
466 char *buf, this, bit;
467 size_t bufsize, bufdata;
470 bufsize = bufdata = 0;
471 for(bit = 4, this = 0; *data; data++)
473 if((*data >= 'A') && (*data <= 'F'))
475 this |= (this & 0x0F) | ((*data - 'A' + 10) << bit);
476 } else if((*data >= 'a') && (*data <= 'f')) {
477 this |= (this & 0x0F) | ((*data - 'a' + 10) << bit);
478 } else if((*data >= '0') && (*data <= '9')) {
479 this |= (this & 0x0F) | ((*data - '0') << bit);
480 } else if(*data == '\n') {
506 char *base64encode(char *data, size_t datalen)
509 size_t bufsize, bufdata;
514 bufsize = bufdata = 0;
517 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
518 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
519 addtobuf(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]);
520 addtobuf(buf, base64set[data[2] & 0x3f]);
526 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
527 addtobuf(buf, base64set[(data[0] & 0x03) << 4]);
528 bufcat(buf, "==", 2);
532 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
533 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
534 addtobuf(buf, base64set[(data[1] & 0x0f) << 2]);
541 char *base64decode(char *data, size_t *datalen)
545 size_t bufsize, bufdata;
548 bufsize = bufdata = 0;
551 for(; *data > 0; data++)
553 c = (int)(unsigned char)*data;
558 if(base64rev[c] == -1)
567 cur |= base64rev[c] >> -b;
572 cur |= base64rev[c] << b;
580 char *base32encode(char *data, size_t datalen)
583 size_t bufsize, bufdata;
588 bufsize = bufdata = 0;
591 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
592 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
593 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
594 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
595 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
596 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
597 addtobuf(buf, base32set[((data[3] & 0x03) << 3) | ((data[4] & 0xe0) >> 5)]);
598 addtobuf(buf, base32set[data[4] & 0x1f]);
604 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
605 addtobuf(buf, base32set[((data[0] & 0x07) << 2)]);
606 bufcat(buf, "======", 6);
610 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
611 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
612 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
613 addtobuf(buf, base32set[((data[1] & 0x01) << 4)]);
614 bufcat(buf, "====", 4);
618 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
619 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
620 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
621 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
622 addtobuf(buf, base32set[((data[2] & 0x0f) << 1)]);
623 bufcat(buf, "===", 3);
627 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
628 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
629 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
630 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
631 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
632 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
633 addtobuf(buf, base32set[((data[3] & 0x03) << 3)]);
640 char *base32decode(char *data, size_t *datalen)
644 size_t bufsize, bufdata;
647 bufsize = bufdata = 0;
650 for(; *data > 0; data++)
652 c = (int)(unsigned char)*data;
657 if(base32rev[c] == -1)
666 cur |= base32rev[c] >> -b;
671 cur |= base32rev[c] << b;
679 void _freeparr(void **arr)
685 for(buf = arr; *buf != NULL; buf++)
690 int _parrlen(void **arr)
696 for(i = 0; *arr != NULL; arr++)
701 char *getetcpath(char *binpath)
705 size_t etcpathsize, etcpathdata;
708 etcpathsize = etcpathdata = 0;
716 for(p = binpath; *p && (*p != ':'); p++);
717 for(; (p >= binpath) && (*p != '/'); p--);
721 addtobuf(etcpath, ':');
722 bufcat(etcpath, binpath, p - binpath + 1);
723 bufcat(etcpath, "etc", 3);
725 } while((binpath = strchr(binpath, ':')) != NULL);
726 addtobuf(etcpath, 0);
730 char *findfile(char *name, char *homedir, int filldef)
732 char *path, *binpath, *etcpath, *p;
739 mode = R_OK | (filldef ? W_OK : 0);
740 homeonly = homedir != NULL;
742 if(!strchr(name, '/'))
745 homedir = getenv("HOME");
746 if((homedir == NULL) && ((pw = getpwuid(getuid())) != NULL))
747 homedir = pw->pw_dir;
748 if((homedir != NULL) && ((path = sprintf2("%s/.%s", homedir, name)) != NULL))
750 if(!access(path, mode))
758 if(strchr(name, '/') != NULL)
760 if(!access(name, mode))
761 return(sstrdup(name));
763 if((binpath = getenv("PATH")) == NULL)
764 etcpath = sstrdup("/usr/local/etc:/etc:/usr/etc");
766 etcpath = getetcpath(binpath);
767 for(p = strtok(etcpath, ":"); p != NULL; p = strtok(NULL, ":"))
769 if((path = sprintf2("%s/%s", p, name)) != NULL)
771 if(!access(path, mode))
785 return(sprintf2("%s/.%s", homedir, name));
786 return(sprintf2("/etc/%s", name));
792 struct strpair *newstrpair(char *key, char *val, struct strpair **list)
794 struct strpair *pair;
796 pair = smalloc(sizeof(*pair));
797 memset(pair, 0, sizeof(*pair));
799 pair->key = sstrdup(key);
801 pair->val = sstrdup(val);
810 void freestrpair(struct strpair *pair, struct strpair **list)
814 for(cur = *list; cur != NULL; list = &(cur->next), cur = cur->next)
827 char *spfind(struct strpair *list, char *key)
829 for(; list != NULL; list = list->next)
831 if(!strcmp(list->key, key))
837 struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list)
839 struct wcspair *pair;
841 pair = smalloc(sizeof(*pair));
842 memset(pair, 0, sizeof(*pair));
844 pair->key = swcsdup(key);
846 pair->val = swcsdup(val);
855 void freewcspair(struct wcspair *pair, struct wcspair **list)
859 for(cur = *list; cur != NULL; list = &(cur->next), cur = cur->next)
872 wchar_t *wpfind(struct wcspair *list, wchar_t *key)
874 for(; list != NULL; list = list->next)
876 if(!wcscmp(list->key, key))
882 static int btheight(struct btree *tree)
889 static void btsetheight(struct btree *tree)
895 lh = btheight(tree->l);
896 rh = btheight(tree->r);
897 tree->h = ((lh > rh)?lh:rh) + 1;
900 static void bbtrl(struct btree **tree);
902 static void bbtrr(struct btree **tree)
904 struct btree *m, *l, *r;
906 if(btheight((*tree)->l->r) > btheight((*tree)->l->l))
918 static void bbtrl(struct btree **tree)
920 struct btree *m, *l, *r;
922 if(btheight((*tree)->r->l) > btheight((*tree)->r->r))
934 int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *))
937 struct btree *s, **sp, *o;
941 if((c = cmp(item, (*tree)->d)) < 0) {
942 r = bbtreedel(&(*tree)->l, item, cmp);
944 r = bbtreedel(&(*tree)->r, item, cmp);
948 if(((*tree)->r != NULL) && ((*tree)->l != NULL)) {
951 while(s->l != NULL) {
959 } else if((*tree)->l != NULL) {
961 } else if((*tree)->r != NULL) {
970 if(btheight((*tree)->l) > btheight((*tree)->r) + 1)
972 if(btheight((*tree)->r) > btheight((*tree)->l) + 1)
978 int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *))
983 *tree = smalloc(sizeof(**tree));
984 (*tree)->l = (*tree)->r = NULL;
989 if((c = cmp(item, (*tree)->d)) < 0)
990 r = bbtreeput(&(*tree)->l, item, cmp);
992 r = bbtreeput(&(*tree)->r, item, cmp);
996 if(btheight((*tree)->l) > btheight((*tree)->r) + 1)
998 if(btheight((*tree)->r) > btheight((*tree)->l) + 1)
1003 void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *))
1010 c = cmp(key, tree->d);
1020 void btreefree(struct btree *tree)
1029 static void *btreenext(void **iterp)
1031 struct treeiter *iter;
1035 if((iter = *iterp) == NULL)
1038 s = iter->st[iter->sp].s;
1039 n = iter->st[iter->sp].n;
1041 iter->st[iter->sp].s = 1;
1044 sizebuf2(iter->st, iter->sp + 1, 1);
1045 iter->st[iter->sp].s = 0;
1046 iter->st[iter->sp].n = n->l;
1049 iter->st[iter->sp].s = 2;
1050 return(iter->st[iter->sp].n->d);
1052 iter->st[iter->sp].s = 3;
1055 sizebuf2(iter->st, iter->sp + 1, 1);
1056 iter->st[iter->sp].s = 0;
1057 iter->st[iter->sp].n = n->r;
1071 static void *btreefirst(struct btree *tree, void **iterp)
1073 struct treeiter *iter;
1079 *iterp = iter = memset(smalloc(sizeof(*iter)), 0, sizeof(*iter));
1080 sizebuf2(iter->st, 1, 1);
1081 iter->st[0].n = tree;
1083 return(btreenext(iterp));
1086 static void btreestop(void **iterp)
1088 struct treeiter *iter;
1090 if((iter = *iterp) == NULL)
1092 if(iter->st != NULL)
1098 void *btreeiter(struct btree *tree)
1100 static void *iter = NULL;
1103 return(btreenext(&iter));
1107 return(btreefirst(tree, &iter));