source: win32.c @ f9dbc99

Last change on this file since f9dbc99 was eecccf1, checked in by Jelmer Vernooij <jelmer@…>, at 2006-05-25T23:08:15Z

Add replacement functions for log_link(), inet_pton() and inet_ntop()

  • Property mode set to 100644
File size: 15.9 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Main file (Windows specific part)                                   */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "commands.h"
29#include "crypting.h"
30#include "protocols/nogaim.h"
31#include "help.h"
32#include <signal.h>
33#include <windows.h>
34
35global_t global;        /* Against global namespace pollution */
36
37static void WINAPI service_ctrl (DWORD dwControl)
38{
39        switch (dwControl)
40        {
41        case SERVICE_CONTROL_STOP:
42                        /* FIXME */
43            break;
44
45        case SERVICE_CONTROL_INTERROGATE:
46            break;
47
48        default:
49            break;
50
51    }
52}
53
54static void bitlbee_init(int argc, char **argv)
55{
56        int i = -1;
57        memset( &global, 0, sizeof( global_t ) );
58       
59        global.loop = g_main_new( FALSE );
60       
61        global.conf = conf_load( argc, argv );
62        if( global.conf == NULL )
63                return;
64       
65        if( global.conf->runmode == RUNMODE_INETD )
66        {
67                i = bitlbee_inetd_init();
68                log_message( LOGLVL_INFO, "Bitlbee %s starting in inetd mode.", BITLBEE_VERSION );
69
70        }
71        else if( global.conf->runmode == RUNMODE_DAEMON )
72        {
73                i = bitlbee_daemon_init();
74                log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );
75        } 
76        else 
77        {
78                log_message( LOGLVL_INFO, "No bitlbee mode specified...");
79        }
80       
81        if( i != 0 )
82                return;
83       
84        if( access( global.conf->configdir, F_OK ) != 0 )
85                log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir );
86        else if( access( global.conf->configdir, 06 ) != 0 )
87                log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
88        if( help_init( &(global.help) ) == NULL )
89                log_message( LOGLVL_WARNING, "Error opening helpfile %s.", global.helpfile );
90}
91
92void service_main (DWORD argc, LPTSTR *argv)
93{
94        SERVICE_STATUS_HANDLE handle;
95        SERVICE_STATUS status;
96
97    handle = RegisterServiceCtrlHandler("bitlbee", service_ctrl);
98
99    if (!handle)
100                return;
101
102    status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
103    status.dwServiceSpecificExitCode = 0;
104
105        bitlbee_init(argc, argv);
106
107        SetServiceStatus(handle, &status);
108       
109        g_main_run( global.loop );
110}
111
112SERVICE_TABLE_ENTRY dispatch_table[] =
113{
114   { TEXT("bitlbee"), (LPSERVICE_MAIN_FUNCTION)service_main },
115   { NULL, NULL }
116};
117
118static int debug = 0;
119
120static void usage()
121{
122        printf("Options:\n");
123        printf("-h   Show this help message\n");
124        printf("-d   Debug mode (simple console program)\n");
125}
126
127int main( int argc, char **argv)
128{   
129        int i;
130        WSADATA WSAData;
131
132        nogaim_init( );
133
134        for (i = 1; i < argc; i++) {
135                if (!strcmp(argv[i], "-d")) debug = 1;
136                if (!strcmp(argv[i], "-h")) {
137                        usage();
138                        return 0;
139                }
140        }
141
142    WSAStartup(MAKEWORD(1,1), &WSAData);
143
144        if (!debug) {
145                if (!StartServiceCtrlDispatcher(dispatch_table))
146                        log_message( LOGLVL_ERROR, "StartServiceCtrlDispatcher failed.");
147        } else {
148                        bitlbee_init(argc, argv);
149                        g_main_run( global.loop );
150        }
151       
152        return 0;
153}
154
155double gettime()
156{
157        return (GetTickCount() / 1000);
158}
159
160void conf_get_string(HKEY section, const char *name, const char *def, char **dest)
161{
162        char buf[4096];
163        long x;
164        if (RegQueryValue(section, name, buf, &x) == ERROR_SUCCESS) {
165                *dest = g_strdup(buf);
166        } else if (!def) {
167                *dest = NULL;
168        } else {
169                *dest = g_strdup(def);
170        }
171}
172
173
174void conf_get_int(HKEY section, const char *name, int def, int *dest)
175{
176        char buf[20];
177        long x;
178        DWORD y;
179        if (RegQueryValue(section, name, buf, &x) == ERROR_SUCCESS) {
180                memcpy(&y, buf, sizeof(DWORD));
181                *dest = y;
182        } else {
183                *dest = def;
184        }
185}
186
187conf_t *conf_load( int argc, char *argv[] ) 
188{
189        conf_t *conf;
190        HKEY key, key_main, key_proxy;
191        char *tmp;
192
193        RegOpenKey(HKEY_CURRENT_USER, "SOFTWARE\\Bitlbee", &key);
194        RegOpenKey(key, "main", &key_main);
195        RegOpenKey(key, "proxy", &key_proxy);
196       
197        memset( &global, 0, sizeof( global_t ) );
198        global.loop = g_main_new(FALSE);
199
200        conf = g_new0( conf_t,1 );
201        global.conf = conf;
202        conf_get_string(key_main, "interface", "0.0.0.0", &global.conf->iface);
203        conf_get_int(key_main, "port", 6667, &global.conf->port);
204        conf_get_int(key_main, "verbose", 0, &global.conf->verbose);
205        conf_get_string(key_main, "auth_pass", "", &global.conf->auth_pass);
206        conf_get_string(key_main, "oper_pass", "", &global.conf->oper_pass);
207        conf_get_int(key_main, "ping_interval_timeout", 60, &global.conf->ping_interval);
208        conf_get_string(key_main, "hostname", "localhost", &global.conf->hostname);
209        conf_get_string(key_main, "configdir", NULL, &global.conf->configdir);
210        conf_get_string(key_main, "motdfile", NULL, &global.conf->motdfile);
211        conf_get_string(key_main, "helpfile", NULL, &global.helpfile);
212        global.conf->runmode = RUNMODE_DAEMON;
213        conf_get_int(key_main, "AuthMode", AUTHMODE_OPEN, &global.conf->authmode);
214        conf_get_string(key_proxy, "host", "", &tmp); strcpy(proxyhost, tmp);
215        conf_get_string(key_proxy, "user", "", &tmp); strcpy(proxyuser, tmp);
216        conf_get_string(key_proxy, "password", "", &tmp); strcpy(proxypass, tmp);
217        conf_get_int(key_proxy, "type", PROXY_NONE, &proxytype);
218        conf_get_int(key_proxy, "port", 3128, &proxyport);
219
220        RegCloseKey(key);
221        RegCloseKey(key_main);
222        RegCloseKey(key_proxy);
223
224        return conf;
225}
226
227void conf_loaddefaults( irc_t *irc )
228{
229        HKEY key_defaults;
230        int i;
231        char name[4096], data[4096];
232        DWORD namelen = sizeof(name), datalen = sizeof(data);
233        DWORD type;
234        if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Bitlbee\\defaults", &key_defaults) != ERROR_SUCCESS) {
235                return;
236        }
237
238        for (i = 0; RegEnumValue(key_defaults, i, name, &namelen, NULL, &type, data, &datalen) == ERROR_SUCCESS; i++) {
239                set_t *s = set_find( irc, name );
240                       
241                if( s )
242                {
243                        if( s->def ) g_free( s->def );
244                        s->def = g_strdup( data );
245                }
246
247                namelen = sizeof(name);
248                datalen = sizeof(data);
249        }
250
251        RegCloseKey(key_defaults);
252}
253
254#ifndef INADDR_NONE
255#define INADDR_NONE 0xffffffff
256#endif
257
258int
259inet_aton(const char *cp, struct in_addr *addr)
260{
261  addr->s_addr = inet_addr(cp);
262  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
263}
264
265void log_error(char *msg)
266{
267        log_message(LOGLVL_ERROR, "%s", msg);
268}
269
270void log_message(int level, char *message, ...)
271{
272    HANDLE  hEventSource;
273    LPTSTR  lpszStrings[2];
274        WORD elevel;
275    va_list ap;
276
277    va_start(ap, message);
278
279        if (debug) {
280                vprintf(message, ap);
281                putchar('\n');
282                va_end(ap);
283                return;
284        }
285
286    hEventSource = RegisterEventSource(NULL, TEXT("bitlbee"));
287
288    lpszStrings[0] = TEXT("bitlbee");
289    lpszStrings[1] = g_strdup_vprintf(message, ap);
290    va_end(ap);
291
292        switch (level) {
293        case LOGLVL_ERROR: elevel = EVENTLOG_ERROR_TYPE; break;
294        case LOGLVL_WARNING: elevel = EVENTLOG_WARNING_TYPE; break;
295        case LOGLVL_INFO: elevel = EVENTLOG_INFORMATION_TYPE; break;
296#ifdef DEBUG
297        case LOGLVL_DEBUG: elevel = EVENTLOG_AUDIT_SUCCESS; break;
298#endif
299        }
300
301    if (hEventSource != NULL) {
302        ReportEvent(hEventSource, 
303        elevel,
304        0,                   
305        0,                   
306        NULL,                 
307        2,                   
308        0,                   
309        lpszStrings,         
310        NULL);               
311
312        DeregisterEventSource(hEventSource);
313    }
314
315        g_free(lpszStrings[1]);
316}
317
318void log_link(int level, int output) { /* FIXME */ }
319
320#ifndef NS_INADDRSZ
321#define NS_INADDRSZ     4
322#endif
323#ifndef NS_IN6ADDRSZ
324#define NS_IN6ADDRSZ    16
325#endif
326#ifndef NS_INT16SZ
327#define NS_INT16SZ      2
328#endif
329
330static const char *inet_ntop4(const guchar *src, char *dst, size_t size);
331static const char *inet_ntop6(const guchar *src, char *dst, size_t size);
332
333/* char *
334 * inet_ntop(af, src, dst, size)
335 *      convert a network format address to presentation format.
336 * return:
337 *      pointer to presentation format address (`dst'), or NULL (see errno).
338 * author:
339 *      Paul Vixie, 1996.
340 */
341const char *
342inet_ntop(af, src, dst, size)
343        int af;
344        const void *src;
345        char *dst;
346        size_t size;
347{
348        switch (af) {
349        case AF_INET:
350                return (inet_ntop4(src, dst, size));
351        case AF_INET6:
352                return (inet_ntop6(src, dst, size));
353        default:
354                errno = WSAEAFNOSUPPORT;
355                return (NULL);
356        }
357        /* NOTREACHED */
358}
359
360/* const char *
361 * inet_ntop4(src, dst, size)
362 *      format an IPv4 address
363 * return:
364 *      `dst' (as a const)
365 * notes:
366 *      (1) uses no statics
367 *      (2) takes a u_char* not an in_addr as input
368 * author:
369 *      Paul Vixie, 1996.
370 */
371static const char *
372inet_ntop4(src, dst, size)
373        const u_char *src;
374        char *dst;
375        size_t size;
376{
377        static const char fmt[] = "%u.%u.%u.%u";
378        char tmp[sizeof "255.255.255.255"];
379        int nprinted;
380
381        nprinted = g_snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
382        if (nprinted < 0)
383                return (NULL);  /* we assume "errno" was set by "g_snprintf()" */
384        if ((size_t)nprinted > size) {
385                errno = ENOSPC;
386                return (NULL);
387        }
388        strcpy(dst, tmp);
389        return (dst);
390}
391
392/* const char *
393 * inet_ntop6(src, dst, size)
394 *      convert IPv6 binary address into presentation (printable) format
395 * author:
396 *      Paul Vixie, 1996.
397 */
398static const char *
399inet_ntop6(src, dst, size)
400        const u_char *src;
401        char *dst;
402        size_t size;
403{
404        /*
405         * Note that int32_t and int16_t need only be "at least" large enough
406         * to contain a value of the specified size.  On some systems, like
407         * Crays, there is no such thing as an integer variable with 16 bits.
408         * Keep this in mind if you think this function should have been coded
409         * to use pointer overlays.  All the world's not a VAX.
410         */
411        char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
412        struct { int base, len; } best, cur;
413        guint words[NS_IN6ADDRSZ / NS_INT16SZ];
414        int i;
415
416        /*
417         * Preprocess:
418         *      Copy the input (bytewise) array into a wordwise array.
419         *      Find the longest run of 0x00's in src[] for :: shorthanding.
420         */
421        memset(words, '\0', sizeof words);
422        for (i = 0; i < NS_IN6ADDRSZ; i++)
423                words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
424        best.base = -1;
425        cur.base = -1;
426        for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
427                if (words[i] == 0) {
428                        if (cur.base == -1)
429                                cur.base = i, cur.len = 1;
430                        else
431                                cur.len++;
432                } else {
433                        if (cur.base != -1) {
434                                if (best.base == -1 || cur.len > best.len)
435                                        best = cur;
436                                cur.base = -1;
437                        }
438                }
439        }
440        if (cur.base != -1) {
441                if (best.base == -1 || cur.len > best.len)
442                        best = cur;
443        }
444        if (best.base != -1 && best.len < 2)
445                best.base = -1;
446
447        /*
448         * Format the result.
449         */
450        tp = tmp;
451        for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
452                /* Are we inside the best run of 0x00's? */
453                if (best.base != -1 && i >= best.base &&
454                    i < (best.base + best.len)) {
455                        if (i == best.base)
456                                *tp++ = ':';
457                        continue;
458                }
459                /* Are we following an initial run of 0x00s or any real hex? */
460                if (i != 0)
461                        *tp++ = ':';
462                /* Is this address an encapsulated IPv4? */
463                if (i == 6 && best.base == 0 &&
464                    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
465                        if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
466                                return (NULL);
467                        tp += strlen(tp);
468                        break;
469                }
470                tp += g_snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]);
471        }
472        /* Was it a trailing run of 0x00's? */
473        if (best.base != -1 && (best.base + best.len) ==
474            (NS_IN6ADDRSZ / NS_INT16SZ))
475                *tp++ = ':';
476        *tp++ = '\0';
477
478        /*
479         * Check for overflow, copy, and we're done.
480         */
481        if ((size_t)(tp - tmp) > size) {
482                errno = ENOSPC;
483                return (NULL);
484        }
485        strcpy(dst, tmp);
486        return (dst);
487}
488
489#ifdef AF_INET
490static int inet_pton4(const char *src, u_char *dst);
491#endif
492#ifdef AF_INET6
493static int inet_pton6(const char *src, u_char *dst);
494#endif
495
496/* int
497 * inet_pton(af, src, dst)
498 *      convert from presentation format (which usually means ASCII printable)
499 *      to network format (which is usually some kind of binary format).
500 * return:
501 *      1 if the address was valid for the specified address family
502 *      0 if the address wasn't valid (`dst' is untouched in this case)
503 *      -1 if some other error occurred (`dst' is untouched in this case, too)
504 * author:
505 *      Paul Vixie, 1996.
506 */
507int
508inet_pton(af, src, dst)
509        int af;
510        const char *src;
511        void *dst;
512{
513        switch (af) {
514#ifdef AF_INET
515        case AF_INET:
516                return (inet_pton4(src, dst));
517#endif
518#ifdef AF_INET6
519        case AF_INET6:
520                return (inet_pton6(src, dst));
521#endif
522        default:
523                errno = WSAEAFNOSUPPORT;
524                return (-1);
525        }
526        /* NOTREACHED */
527}
528
529#ifdef AF_INET
530/* int
531 * inet_pton4(src, dst)
532 *      like inet_aton() but without all the hexadecimal and shorthand.
533 * return:
534 *      1 if `src' is a valid dotted quad, else 0.
535 * notice:
536 *      does not touch `dst' unless it's returning 1.
537 * author:
538 *      Paul Vixie, 1996.
539 */
540static int
541inet_pton4(src, dst)
542        const char *src;
543        u_char *dst;
544{
545        static const char digits[] = "0123456789";
546        int saw_digit, octets, ch;
547        u_char tmp[NS_INADDRSZ], *tp;
548
549        saw_digit = 0;
550        octets = 0;
551        *(tp = tmp) = 0;
552        while ((ch = *src++) != '\0') {
553                const char *pch;
554
555                if ((pch = strchr(digits, ch)) != NULL) {
556                        u_int new = *tp * 10 + (pch - digits);
557
558                        if (new > 255)
559                                return (0);
560                        *tp = new;
561                        if (! saw_digit) {
562                                if (++octets > 4)
563                                        return (0);
564                                saw_digit = 1;
565                        }
566                } else if (ch == '.' && saw_digit) {
567                        if (octets == 4)
568                                return (0);
569                        *++tp = 0;
570                        saw_digit = 0;
571                } else
572                        return (0);
573        }
574        if (octets < 4)
575                return (0);
576        memcpy(dst, tmp, NS_INADDRSZ);
577        return (1);
578}
579#endif
580
581#ifdef AF_INET6
582/* int
583 * inet_pton6(src, dst)
584 *      convert presentation level address to network order binary form.
585 * return:
586 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
587 * notice:
588 *      (1) does not touch `dst' unless it's returning 1.
589 *      (2) :: in a full address is silently ignored.
590 * credit:
591 *      inspired by Mark Andrews.
592 * author:
593 *      Paul Vixie, 1996.
594 */
595static int
596inet_pton6(src, dst)
597        const char *src;
598        u_char *dst;
599{
600        static const char xdigits_l[] = "0123456789abcdef",
601                          xdigits_u[] = "0123456789ABCDEF";
602        u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
603        const char *xdigits, *curtok;
604        int ch, saw_xdigit;
605        u_int val;
606
607        memset((tp = tmp), '\0', NS_IN6ADDRSZ);
608        endp = tp + NS_IN6ADDRSZ;
609        colonp = NULL;
610        /* Leading :: requires some special handling. */
611        if (*src == ':')
612                if (*++src != ':')
613                        return (0);
614        curtok = src;
615        saw_xdigit = 0;
616        val = 0;
617        while ((ch = *src++) != '\0') {
618                const char *pch;
619
620                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
621                        pch = strchr((xdigits = xdigits_u), ch);
622                if (pch != NULL) {
623                        val <<= 4;
624                        val |= (pch - xdigits);
625                        if (val > 0xffff)
626                                return (0);
627                        saw_xdigit = 1;
628                        continue;
629                }
630                if (ch == ':') {
631                        curtok = src;
632                        if (!saw_xdigit) {
633                                if (colonp)
634                                        return (0);
635                                colonp = tp;
636                                continue;
637                        } else if (*src == '\0') {
638                                return (0);
639                        }
640                        if (tp + NS_INT16SZ > endp)
641                                return (0);
642                        *tp++ = (u_char) (val >> 8) & 0xff;
643                        *tp++ = (u_char) val & 0xff;
644                        saw_xdigit = 0;
645                        val = 0;
646                        continue;
647                }
648                if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
649                    inet_pton4(curtok, tp) > 0) {
650                        tp += NS_INADDRSZ;
651                        saw_xdigit = 0;
652                        break;  /* '\0' was seen by inet_pton4(). */
653                }
654                return (0);
655        }
656        if (saw_xdigit) {
657                if (tp + NS_INT16SZ > endp)
658                        return (0);
659                *tp++ = (u_char) (val >> 8) & 0xff;
660                *tp++ = (u_char) val & 0xff;
661        }
662        if (colonp != NULL) {
663                /*
664                 * Since some memmove()'s erroneously fail to handle
665                 * overlapping regions, we'll do the shift by hand.
666                 */
667                const int n = tp - colonp;
668                int i;
669
670                if (tp == endp)
671                        return (0);
672                for (i = 1; i <= n; i++) {
673                        endp[- i] = colonp[n - i];
674                        colonp[n - i] = 0;
675                }
676                tp = endp;
677        }
678        if (tp != endp)
679                return (0);
680        memcpy(dst, tmp, NS_IN6ADDRSZ);
681        return (1);
682}
683#endif
Note: See TracBrowser for help on using the repository browser.