1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77#include <config.h>
78#include "dcethread-debug.h"
79#include <stdarg.h>
80#include <stdlib.h>
81#include <stdio.h>
82#include <pthread.h>
83
84pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER;
85
86void
87dcethread__default_log_callback (const char* file, unsigned int line,
88	int level, const char* str, void* data ATTRIBUTE_UNUSED)
89{
90    const char* level_name = NULL;
91
92    switch (level)
93    {
94    case DCETHREAD_DEBUG_ERROR:
95        level_name = "ERROR";
96        break;
97    case DCETHREAD_DEBUG_WARNING:
98        level_name = "WARNING";
99        break;
100    case DCETHREAD_DEBUG_INFO:
101        level_name = "INFO";
102        break;
103    case DCETHREAD_DEBUG_VERBOSE:
104        level_name = "VERBOSE";
105        break;
106    case DCETHREAD_DEBUG_TRACE:
107        level_name = "TRACE";
108        break;
109    default:
110        level_name = "UNKNOWN";
111        break;
112    }
113
114    pthread_mutex_lock(&log_lock);
115    fprintf(stderr, "dcethread-%s %s:%i: %s\n", level_name, file, line, str);
116    if (level == DCETHREAD_DEBUG_ERROR)
117        abort();
118    pthread_mutex_unlock(&log_lock);
119}
120
121static void (*log_callback) (const char* file, unsigned int line, int level, const char* str, void* data) = NULL;
122static void *log_callback_data = NULL;
123
124void
125dcethread__debug_set_callback(void (*cb) (const char*, unsigned int, int, const char*, void* data), void* data)
126{
127    log_callback = cb;
128    log_callback_data = data;
129}
130
131#ifndef HAVE_VASPRINTF
132static char *
133my_vasprintf(const char* format, va_list args)
134{
135    char *smallBuffer;
136    unsigned int bufsize;
137    int requiredLength;
138    int newRequiredLength;
139    char* outputString = NULL;
140    va_list args2;
141
142    va_copy(args2, args);
143
144    bufsize = 4;
145    /* Use a small buffer in case libc does not like NULL */
146    do
147    {
148        smallBuffer = malloc(bufsize);
149
150	if (!smallBuffer)
151	{
152	    return NULL;
153	}
154
155        requiredLength = vsnprintf(smallBuffer, bufsize, format, args);
156        if (requiredLength < 0)
157        {
158            bufsize *= 2;
159        }
160	free(smallBuffer);
161    } while (requiredLength < 0);
162
163    if (requiredLength >= (int)(0xFFFFFFFF - 1))
164    {
165        return NULL;
166    }
167
168    outputString = malloc(requiredLength + 2);
169
170    if (!outputString)
171    {
172	return NULL;
173    }
174
175    newRequiredLength = vsnprintf(outputString, requiredLength + 1, format, args2);
176    if (newRequiredLength < 0)
177    {
178	free(outputString);
179	return NULL;
180    }
181
182    va_end(args2);
183
184    return outputString;
185}
186#endif /* HAVE_VASPRINTF */
187
188void
189dcethread__debug_printf(const char* file, unsigned int line, int level, const char* fmt, ...)
190{
191    va_list ap;
192    char* str = NULL;
193
194    if (!log_callback)
195	return;
196
197    va_start(ap, fmt);
198
199#if HAVE_VASPRINTF
200    vasprintf(&str, fmt, ap);
201#else
202    str = my_vasprintf(fmt, ap);
203#endif
204
205    if (str)
206    {
207	log_callback(file, line, level, str, log_callback_data);
208	free(str);
209    }
210
211    va_end(ap);
212}
213