Disallow cross-user messages.
[doldaconnect.git] / daemon / utils.c
... / ...
CommitLineData
1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
4 *
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.
9 *
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.
14 *
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
18*/
19#include <malloc.h>
20#include <stdarg.h>
21#include <stdio.h>
22#include <wchar.h>
23#include <iconv.h>
24#include <errno.h>
25#include <string.h>
26#include <wctype.h>
27#include <langinfo.h>
28#include <pwd.h>
29#include <unistd.h>
30#include <sys/time.h>
31#include <netinet/in.h>
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36#include "utils.h"
37#include "log.h"
38
39static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
40static int base64rev[] = {
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, 62, -1, -1, -1, 63,
44 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
45 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
46 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
47 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
48 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
49 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57};
58static char *base32set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
59static int base32rev[] = {
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, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
65 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
66 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
67 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76};
77
78char *vsprintf2(char *format, va_list al)
79{
80 int ret;
81 char *buf;
82
83 ret = vsnprintf(NULL, 0, format, al);
84 if((buf = malloc(ret + 1)) == NULL)
85 {
86 LOGOOM(ret + 1);
87 return(NULL);
88 }
89 vsnprintf(buf, ret + 1, format, al);
90 return(buf);
91}
92
93char *sprintf2(char *format, ...)
94{
95 va_list args;
96 char *buf;
97
98 va_start(args, format);
99 buf = vsprintf2(format, args);
100 va_end(args);
101 return(buf);
102}
103
104wchar_t *vswprintf2(wchar_t *format, va_list al)
105{
106 int ret;
107 wchar_t *buf;
108 size_t bufsize;
109
110 buf = smalloc(sizeof(wchar_t) * (bufsize = 1024));
111 while((ret = vswprintf(buf, bufsize, format, al)) < 0)
112 buf = srealloc(buf, sizeof(wchar_t) * (bufsize *= 2));
113 if(bufsize > ret + 1)
114 buf = srealloc(buf, sizeof(wchar_t) * (ret + 1));
115 return(buf);
116}
117
118wchar_t *swprintf2(wchar_t *format, ...)
119{
120 va_list args;
121 wchar_t *buf;
122
123 va_start(args, format);
124 buf = vswprintf2(format, args);
125 va_end(args);
126 return(buf);
127}
128
129int havecharset(char *charset)
130{
131 iconv_t cd;
132
133 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
134 return(0);
135 iconv_close(cd);
136 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
137 return(0);
138 iconv_close(cd);
139 return(1);
140}
141
142wchar_t *icmbstowcs(char *mbs, char *charset)
143{
144 int ret;
145 char *buf;
146 char *p, *p2;
147 size_t len1, len2, bufsize, data;
148 iconv_t cd;
149
150 len1 = strlen(mbs) + 1;
151 bufsize = len2 = len1 * sizeof(wchar_t);
152 if((buf = malloc(bufsize)) == NULL)
153 {
154 LOGOOM(bufsize);
155 return(NULL);
156 }
157 if(charset == NULL)
158 charset = nl_langinfo(CODESET);
159 if((cd = iconv_open("wchar_t", charset)) == (iconv_t)-1)
160 {
161 flog(LOG_ERR, "icmbstowcs: could not open iconv structure for %s: %s", charset, strerror(errno));
162 free(buf);
163 return(NULL);
164 }
165 p = buf;
166 while(len1 > 0)
167 {
168 ret = iconv(cd, &mbs, &len1, &p, &len2);
169 if(ret < 0)
170 {
171 if(errno == E2BIG)
172 {
173 data = p - buf;
174 len2 += 128;
175 bufsize += 128;
176 if((p2 = realloc(buf, bufsize)) == NULL)
177 {
178 LOGOOM(bufsize);
179 free(buf);
180 iconv_close(cd);
181 return(NULL);
182 }
183 buf = p2;
184 p = buf + data;
185 } else {
186 free(buf);
187 iconv_close(cd);
188 return(NULL);
189 }
190 }
191 }
192 if(len2 > 0)
193 buf = realloc(buf, p - buf);
194 iconv_close(cd);
195 return((wchar_t *)buf);
196}
197
198wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def)
199{
200 static wchar_t *buf = NULL;
201
202 if(buf != NULL)
203 free(buf);
204 if((buf = icmbstowcs(mbs, charset)) == NULL)
205 {
206 if((def != NULL) && (*def == L'~'))
207 {
208 flog(LOG_WARNING, "icsmbstowcs: could not convert wcs string into charset %s: %s", charset, strerror(errno));
209 def++;
210 }
211 return(def);
212 }
213 return(buf);
214}
215
216char *icwcstombs(wchar_t *wcs, char *charset)
217{
218 int ret;
219 char *buf;
220 char *p, *p2;
221 size_t len1, len2, bufsize, data;
222 iconv_t cd;
223
224 len1 = sizeof(wchar_t) * (wcslen(wcs) + 1);
225 bufsize = len2 = len1;
226 if((buf = malloc(bufsize)) == NULL)
227 {
228 LOGOOM(bufsize);
229 return(NULL);
230 }
231 if(charset == NULL)
232 charset = nl_langinfo(CODESET);
233 if((cd = iconv_open(charset, "wchar_t")) == (iconv_t)-1)
234 {
235 flog(LOG_ERR, "icwcstombs: could not open iconv structure for %s: %s", charset, strerror(errno));
236 free(buf);
237 return(NULL);
238 }
239 p = buf;
240 while(len1 > 0)
241 {
242 ret = iconv(cd, (char **)&wcs, &len1, &p, &len2);
243 if(ret < 0)
244 {
245 if(errno == E2BIG)
246 {
247 data = p - buf;
248 len2 += 128;
249 bufsize += 128;
250 if((p2 = realloc(buf, bufsize)) == NULL)
251 {
252 LOGOOM(bufsize);
253 free(buf);
254 iconv_close(cd);
255 return(NULL);
256 }
257 buf = p2;
258 p = buf + data;
259 } else {
260 free(buf);
261 iconv_close(cd);
262 return(NULL);
263 }
264 }
265 }
266 if(len2 > 0)
267 buf = realloc(buf, p - buf);
268 iconv_close(cd);
269 return(buf);
270}
271
272char *icswcstombs(wchar_t *wcs, char *charset, char *def)
273{
274 static char *buf = NULL;
275
276 if(buf != NULL)
277 free(buf);
278 if((buf = icwcstombs(wcs, charset)) == NULL)
279 {
280 if((def != NULL) && (*def == '~'))
281 {
282 flog(LOG_WARNING, "icswcstombs: could not convert mbs string from charset %s: %s", charset, strerror(errno));
283 def++;
284 }
285 return(def);
286 }
287 return(buf);
288}
289
290wchar_t *wcstolower(wchar_t *wcs)
291{
292 wchar_t *p;
293
294 for(p = wcs; *p != L'\0'; p++)
295 *p = towlower(*p);
296 return(wcs);
297}
298
299wchar_t ucptowc(int ucp)
300{
301 int ret;
302 unsigned long ucpbuf;
303 char *buf;
304 char *mbsp, *p, *p2;
305 wchar_t res;
306 size_t len1, len2, bufsize, data;
307 iconv_t cd;
308
309 ucpbuf = htonl(ucp);
310 mbsp = (char *)&ucpbuf;
311 len1 = 4;
312 bufsize = len2 = len1 * sizeof(wchar_t);
313 if((buf = malloc(bufsize)) == NULL)
314 {
315 LOGOOM(bufsize);
316 return(L'\0');
317 }
318 if((cd = iconv_open("wchar_t", "UCS-4BE")) == (iconv_t)-1)
319 {
320 flog(LOG_ERR, "ucptowc: could not open iconv structure for UCS-4BE: %s", strerror(errno));
321 free(buf);
322 return(L'\0');
323 }
324 p = buf;
325 while(len1 > 0)
326 {
327 ret = iconv(cd, &mbsp, &len1, &p, &len2);
328 if(ret < 0)
329 {
330 if(errno == E2BIG)
331 {
332 data = p - buf;
333 len2 += 128;
334 bufsize += 128;
335 if((p2 = realloc(buf, bufsize)) == NULL)
336 {
337 LOGOOM(bufsize);
338 free(buf);
339 iconv_close(cd);
340 return(L'\0');
341 }
342 buf = p2;
343 p = buf + data;
344 } else {
345 free(buf);
346 iconv_close(cd);
347 return(L'\0');
348 }
349 }
350 }
351 if(len2 > 0)
352 buf = realloc(buf, p - buf);
353 iconv_close(cd);
354 res = *(wchar_t *)buf;
355 free(buf);
356 return(res);
357}
358
359void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo)
360{
361 if(*bufsize >= reqsize)
362 return;
363 switch(algo)
364 {
365 case 0:
366 *buf = srealloc(*buf, elsize * ((*bufsize) = reqsize));
367 break;
368 case 1:
369 if(*bufsize == 0)
370 *bufsize = 1;
371 while(*bufsize < reqsize)
372 *bufsize <<= 1;
373 *buf = srealloc(*buf, elsize * (*bufsize));
374 break;
375 }
376}
377
378double ntime(void)
379{
380 struct timeval tv;
381
382 gettimeofday(&tv, NULL);
383 return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
384}
385
386int wcsexists(wchar_t *h, wchar_t *n)
387{
388 int i, o, nl, hl;
389 wchar_t *ln, *lh;
390
391 ln = alloca(sizeof(*ln) * (nl = wcslen(n)));
392 for(i = 0; i < nl; i++)
393 ln[i] = towlower(n[i]);
394 lh = alloca(sizeof(*lh) * (hl = wcslen(h)));
395 if(nl > hl)
396 return(0);
397 for(i = 0; i < nl; i++)
398 lh[i] = towlower(h[i]);
399 i = 0;
400 while(1)
401 {
402 for(o = 0; o < nl; o++)
403 {
404 if(lh[i + o] != ln[o])
405 break;
406 }
407 if(o == nl)
408 return(1);
409 if(i == hl - nl)
410 return(0);
411 lh[i + nl] = towlower(h[i + nl]);
412 i++;
413 }
414}
415
416#ifndef HAVE_WCSCASECMP
417int wcscasecmp(const wchar_t *s1, const wchar_t *s2)
418{
419 while(towlower(*s1) == towlower(*s2))
420 {
421 if(*s1 == L'\0')
422 return(0);
423 }
424 return(towlower(*s1) - towlower(*s2));
425}
426#endif
427
428char *hexencode(char *data, size_t datalen)
429{
430 char *buf, this;
431 size_t bufsize, bufdata;
432 int dig;
433
434 buf = NULL;
435 bufsize = bufdata = 0;
436 for(; datalen > 0; datalen--, data++)
437 {
438 dig = (*data & 0xF0) >> 4;
439 if(dig > 9)
440 this = 'A' + dig - 10;
441 else
442 this = dig + '0';
443 addtobuf(buf, this);
444 dig = *data & 0x0F;
445 if(dig > 9)
446 this = 'A' + dig - 10;
447 else
448 this = dig + '0';
449 addtobuf(buf, this);
450 }
451 addtobuf(buf, 0);
452 return(buf);
453}
454
455char *hexdecode(char *data, size_t *len)
456{
457 char *buf, this;
458 size_t bufsize, bufdata;
459
460 buf = NULL;
461 bufsize = bufdata = 0;
462 for(; *data; data++)
463 {
464 if((*data >= 'A') && (*data <= 'F'))
465 {
466 this = (this & 0x0F) | ((*data - 'A' + 10) << 4);
467 } else if((*data >= '0') && (*data <= '9')) {
468 this = (this & 0x0F) | ((*data - '0') << 4);
469 } else {
470 if(buf != NULL)
471 free(buf);
472 return(NULL);
473 }
474 data++;
475 if(!*data)
476 {
477 if(buf != NULL)
478 free(buf);
479 return(NULL);
480 }
481 if((*data >= 'A') && (*data <= 'F'))
482 {
483 this = (this & 0xF0) | (*data - 'A' + 10);
484 } else if((*data >= '0') && (*data <= '9')) {
485 this = (this & 0xF0) | (*data - '0');
486 } else {
487 if(buf != NULL)
488 free(buf);
489 return(NULL);
490 }
491 addtobuf(buf, this);
492 }
493 addtobuf(buf, 0);
494 if(len != NULL)
495 *len = bufdata - 1;
496 return(buf);
497}
498
499char *base64encode(char *data, size_t datalen)
500{
501 char *buf;
502 size_t bufsize, bufdata;
503
504 if(datalen == 0)
505 return(sstrdup(""));
506 buf = NULL;
507 bufsize = bufdata = 0;
508 while(datalen >= 3)
509 {
510 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
511 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
512 addtobuf(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]);
513 addtobuf(buf, base64set[data[2] & 0x3f]);
514 datalen -= 3;
515 data += 3;
516 }
517 if(datalen == 1)
518 {
519 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
520 addtobuf(buf, base64set[(data[0] & 0x03) << 4]);
521 bufcat(buf, "==", 2);
522 }
523 if(datalen == 2)
524 {
525 addtobuf(buf, base64set[(data[0] & 0xfc) >> 2]);
526 addtobuf(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]);
527 addtobuf(buf, base64set[(data[1] & 0x0f) << 2]);
528 addtobuf(buf, '=');
529 }
530 addtobuf(buf, 0);
531 return(buf);
532}
533
534char *base64decode(char *data, size_t *datalen)
535{
536 int b, c;
537 char *buf, cur;
538 size_t bufsize, bufdata;
539
540 buf = NULL;
541 bufsize = bufdata = 0;
542 cur = 0;
543 b = 8;
544 for(; *data > 0; data++)
545 {
546 c = (int)(unsigned char)*data;
547 if(c == '=')
548 break;
549 if(c == '\n')
550 continue;
551 if(base64rev[c] == -1)
552 {
553 if(buf != NULL)
554 free(buf);
555 return(NULL);
556 }
557 b -= 6;
558 if(b <= 0)
559 {
560 cur |= base64rev[c] >> -b;
561 addtobuf(buf, cur);
562 b += 8;
563 cur = 0;
564 }
565 cur |= base64rev[c] << b;
566 }
567 if(datalen != NULL)
568 *datalen = bufdata;
569 addtobuf(buf, 0);
570 return(buf);
571}
572
573char *base32encode(char *data, size_t datalen)
574{
575 char *buf;
576 size_t bufsize, bufdata;
577
578 if(datalen == 0)
579 return(sstrdup(""));
580 buf = NULL;
581 bufsize = bufdata = 0;
582 while(datalen >= 5)
583 {
584 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
585 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
586 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
587 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
588 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
589 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
590 addtobuf(buf, base32set[((data[3] & 0x03) << 3) | ((data[4] & 0xe0) >> 5)]);
591 addtobuf(buf, base32set[data[4] & 0x1f]);
592 datalen -= 5;
593 data += 5;
594 }
595 if(datalen == 1)
596 {
597 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
598 addtobuf(buf, base32set[((data[0] & 0x07) << 2)]);
599 bufcat(buf, "======", 6);
600 }
601 if(datalen == 2)
602 {
603 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
604 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
605 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
606 addtobuf(buf, base32set[((data[1] & 0x01) << 4)]);
607 bufcat(buf, "====", 4);
608 }
609 if(datalen == 3)
610 {
611 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
612 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
613 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
614 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
615 addtobuf(buf, base32set[((data[2] & 0x0f) << 1)]);
616 bufcat(buf, "===", 3);
617 }
618 if(datalen == 4)
619 {
620 addtobuf(buf, base32set[((data[0] & 0xf8) >> 3)]);
621 addtobuf(buf, base32set[((data[0] & 0x07) << 2) | ((data[1] & 0xc0) >> 6)]);
622 addtobuf(buf, base32set[((data[1] & 0x3e) >> 1)]);
623 addtobuf(buf, base32set[((data[1] & 0x01) << 4) | ((data[2] & 0xf0) >> 4)]);
624 addtobuf(buf, base32set[((data[2] & 0x0f) << 1) | ((data[3] & 0x80) >> 7)]);
625 addtobuf(buf, base32set[((data[3] & 0x7c) >> 2)]);
626 addtobuf(buf, base32set[((data[3] & 0x03) << 3)]);
627 bufcat(buf, "=", 1);
628 }
629 addtobuf(buf, 0);
630 return(buf);
631}
632
633char *base32decode(char *data, size_t *datalen)
634{
635 int b, c;
636 char *buf, cur;
637 size_t bufsize, bufdata;
638
639 buf = NULL;
640 bufsize = bufdata = 0;
641 cur = 0;
642 b = 8;
643 for(; *data > 0; data++)
644 {
645 c = (int)(unsigned char)*data;
646 if(c == '=')
647 break;
648 if(c == '\n')
649 continue;
650 if(base32rev[c] == -1)
651 {
652 if(buf != NULL)
653 free(buf);
654 return(NULL);
655 }
656 b -= 5;
657 if(b <= 0)
658 {
659 cur |= base32rev[c] >> -b;
660 addtobuf(buf, cur);
661 b += 8;
662 cur = 0;
663 }
664 cur |= base32rev[c] << b;
665 }
666 if(datalen != NULL)
667 *datalen = bufdata;
668 addtobuf(buf, 0);
669 return(buf);
670}
671
672void _freeparr(void **arr)
673{
674 void **buf;
675
676 if(arr == NULL)
677 return;
678 for(buf = arr; *buf != NULL; buf++)
679 free(*buf);
680 free(arr);
681}
682
683int _parrlen(void **arr)
684{
685 int i;
686
687 if(arr == NULL)
688 return(0);
689 for(i = 0; *arr != NULL; arr++)
690 i++;
691 return(i);
692}
693
694char *getetcpath(char *binpath)
695{
696 int f;
697 char *etcpath, *p;
698 size_t etcpathsize, etcpathdata;
699
700 etcpath = NULL;
701 etcpathsize = etcpathdata = 0;
702 f = 1;
703 do
704 {
705 if(f)
706 f = 0;
707 else
708 binpath++;
709 for(p = binpath; *p && (*p != ':'); p++);
710 for(; (p >= binpath) && (*p != '/'); p--);
711 if(p >= binpath)
712 {
713 if(etcpathdata > 0)
714 addtobuf(etcpath, ':');
715 bufcat(etcpath, binpath, p - binpath + 1);
716 bufcat(etcpath, "etc", 3);
717 }
718 } while((binpath = strchr(binpath, ':')) != NULL);
719 addtobuf(etcpath, 0);
720 return(etcpath);
721}
722
723char *findfile(char *gname, char *uname, char *homedir, int filldef)
724{
725 char *path, *binpath, *etcpath, *p;
726 struct passwd *pw;
727
728 if(uname != NULL) {
729 if((homedir == NULL) && ((pw = getpwuid(getuid())) != NULL))
730 homedir = pw->pw_dir;
731 if((homedir != NULL) && ((path = sprintf2("%s/.%s", homedir, uname)) != NULL))
732 {
733 if(!access(path, F_OK))
734 return(path);
735 free(path);
736 }
737 }
738 if(gname != NULL)
739 {
740 if(strchr(gname, '/') != NULL)
741 {
742 if(!access(gname, F_OK))
743 return(sstrdup(gname));
744 } else {
745 if((binpath = getenv("PATH")) == NULL)
746 etcpath = sstrdup("/usr/local/etc:/etc:/usr/etc");
747 else
748 etcpath = getetcpath(binpath);
749 for(p = strtok(etcpath, ":"); p != NULL; p = strtok(NULL, ":"))
750 {
751 if((path = sprintf2("%s/%s", p, gname)) != NULL)
752 {
753 if(!access(path, F_OK))
754 {
755 free(etcpath);
756 return(path);
757 }
758 free(path);
759 }
760 }
761 free(etcpath);
762 }
763 }
764 if(filldef) {
765 if(uname && homedir)
766 return("%s/.%s", homedir, uname);
767 return("/etc/%s", gname);
768 } else {
769 return(NULL);
770 }
771}
772
773struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list)
774{
775 struct wcspair *pair;
776
777 pair = smalloc(sizeof(*pair));
778 memset(pair, 0, sizeof(*pair));
779 if(key != NULL)
780 pair->key = swcsdup(key);
781 if(val != NULL)
782 pair->val = swcsdup(val);
783 if(list == NULL)
784 {
785 pair->next = NULL;
786 } else {
787 pair->next = *list;
788 *list = pair;
789 }
790 return(pair);
791}
792
793void freewcspair(struct wcspair *pair, struct wcspair **list)
794{
795 struct wcspair *cur;
796
797 for(cur = *list; cur != NULL; list = &(cur->next), cur = cur->next)
798 {
799 if(cur == pair)
800 {
801 *list = cur->next;
802 break;
803 }
804 }
805 free(pair->key);
806 free(pair->val);
807 free(pair);
808}
809
810wchar_t *wpfind(struct wcspair *list, wchar_t *key)
811{
812 for(; list != NULL; list = list->next)
813 {
814 if(!wcscmp(list->key, key))
815 return(list->val);
816 }
817 return(NULL);
818}