1/*	$NetBSD$	*/
2
3/* OpenLDAP: pkg/ldap/libraries/liblber/bprint.c,v 1.57.2.6 2010/04/13 20:22:53 kurt Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2010 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17/*
18 * Copyright (c) 1991 Regents of the University of Michigan.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms are permitted
22 * provided that this notice is preserved and that due credit is given
23 * to the University of Michigan at Ann Arbor. The name of the University
24 * may not be used to endorse or promote products derived from this
25 * software without specific prior written permission. This software
26 * is provided ``as is'' without express or implied warranty.
27 */
28/* ACKNOWLEDGEMENTS:
29 * This work was originally developed by the University of Michigan
30 * (as part of U-MICH LDAP).
31 */
32
33#include "portable.h"
34
35#include <stdio.h>
36
37#include <ac/ctype.h>
38#include <ac/stdarg.h>
39#include <ac/string.h>
40
41#include "lber-int.h"
42
43#define	ber_log_check(errlvl, loglvl)	((errlvl) & (loglvl))
44
45BER_LOG_FN ber_int_log_proc = NULL;
46
47/*
48 * We don't just set ber_pvt_err_file to stderr here, because in NT,
49 * stderr is a symbol imported from a DLL. As such, the compiler
50 * doesn't recognize the symbol as having a constant address. Thus
51 * we set ber_pvt_err_file to stderr later, when it first gets
52 * referenced.
53 */
54FILE *ber_pvt_err_file = NULL;
55
56/*
57 * ber errno
58 */
59BER_ERRNO_FN ber_int_errno_fn = NULL;
60
61int * ber_errno_addr(void)
62{
63	static int ber_int_errno = LBER_ERROR_NONE;
64
65	if( ber_int_errno_fn ) {
66		return (*ber_int_errno_fn)();
67	}
68
69	return &ber_int_errno;
70}
71
72/*
73 * Print stuff
74 */
75void ber_error_print( LDAP_CONST char *data )
76{
77	assert( data != NULL );
78
79	if (!ber_pvt_err_file) ber_pvt_err_file = stderr;
80
81	fputs( data, ber_pvt_err_file );
82
83	/* Print to both streams */
84	if (ber_pvt_err_file != stderr) {
85		fputs( data, stderr );
86		fflush( stderr );
87	}
88
89	fflush( ber_pvt_err_file );
90}
91
92BER_LOG_PRINT_FN ber_pvt_log_print = ber_error_print;
93
94/*
95 * lber log
96 */
97
98int ber_pvt_log_output(
99	const char *subsystem,
100	int level,
101	const char *fmt,
102	... )
103{
104	char buf[1024];
105	va_list vl;
106	va_start( vl, fmt );
107
108	if ( ber_int_log_proc != NULL ) {
109		ber_int_log_proc( ber_pvt_err_file, subsystem, level, fmt, vl );
110
111	} else {
112		int level;
113		ber_get_option( NULL, LBER_OPT_BER_DEBUG, &level );
114		buf[sizeof(buf) - 1] = '\0';
115		vsnprintf( buf, sizeof(buf)-1, fmt, vl );
116		if ( ber_log_check( LDAP_DEBUG_BER, level ) ) {
117			(*ber_pvt_log_print)( buf );
118		}
119	}
120
121	va_end(vl);
122	return 1;
123}
124
125int ber_pvt_log_printf( int errlvl, int loglvl, const char *fmt, ... )
126{
127	char buf[1024];
128	va_list ap;
129
130	assert( fmt != NULL );
131
132	if ( !ber_log_check( errlvl, loglvl )) {
133		return 0;
134	}
135
136	va_start( ap, fmt );
137
138	buf[sizeof(buf) - 1] = '\0';
139	vsnprintf( buf, sizeof(buf)-1, fmt, ap );
140
141	va_end(ap);
142
143	(*ber_pvt_log_print)( buf );
144	return 1;
145}
146
147#if 0
148static int ber_log_puts(int errlvl, int loglvl, char *buf)
149{
150	assert( buf != NULL );
151
152	if ( !ber_log_check( errlvl, loglvl )) {
153		return 0;
154	}
155
156	(*ber_pvt_log_print)( buf );
157	return 1;
158}
159#endif
160
161/*
162 * Print arbitrary stuff, for debugging.
163 */
164
165int
166ber_log_bprint(int errlvl,
167	int loglvl,
168	const char *data,
169	ber_len_t len )
170{
171	assert( data != NULL );
172
173	if ( !ber_log_check( errlvl, loglvl )) {
174		return 0;
175	}
176
177	ber_bprint(data, len);
178	return 1;
179}
180
181void
182ber_bprint(
183	LDAP_CONST char *data,
184	ber_len_t len )
185{
186	static const char hexdig[] = "0123456789abcdef";
187#define BP_OFFSET 9
188#define BP_GRAPH 60
189#define BP_LEN	80
190	char	line[BP_LEN];
191	ber_len_t i;
192
193	assert( data != NULL );
194
195	/* in case len is zero */
196	line[0] = '\n';
197	line[1] = '\0';
198
199	for ( i = 0 ; i < len ; i++ ) {
200		int n = i % 16;
201		unsigned off;
202
203		if( !n ) {
204			if( i ) (*ber_pvt_log_print)( line );
205			memset( line, ' ', sizeof(line)-2 );
206			line[sizeof(line)-2] = '\n';
207			line[sizeof(line)-1] = '\0';
208
209			off = i % 0x0ffffU;
210
211			line[2] = hexdig[0x0f & (off >> 12)];
212			line[3] = hexdig[0x0f & (off >>  8)];
213			line[4] = hexdig[0x0f & (off >>  4)];
214			line[5] = hexdig[0x0f & off];
215			line[6] = ':';
216		}
217
218		off = BP_OFFSET + n*3 + ((n >= 8)?1:0);
219		line[off] = hexdig[0x0f & ( data[i] >> 4 )];
220		line[off+1] = hexdig[0x0f & data[i]];
221
222		off = BP_GRAPH + n + ((n >= 8)?1:0);
223
224		if ( isprint( (unsigned char) data[i] )) {
225			line[BP_GRAPH + n] = data[i];
226		} else {
227			line[BP_GRAPH + n] = '.';
228		}
229	}
230
231	(*ber_pvt_log_print)( line );
232}
233
234
235int
236ber_log_dump(
237	int errlvl,
238	int loglvl,
239	BerElement *ber,
240	int inout )
241{
242	assert( ber != NULL );
243	assert( LBER_VALID( ber ) );
244
245	if ( !ber_log_check( errlvl, loglvl )) {
246		return 0;
247	}
248
249	ber_dump(ber, inout);
250	return 1;
251}
252
253void
254ber_dump(
255	BerElement *ber,
256	int inout )
257{
258	char buf[132];
259	ber_len_t len;
260
261	assert( ber != NULL );
262	assert( LBER_VALID( ber ) );
263
264	if ( inout == 1 ) {
265		len = ber_pvt_ber_remaining(ber);
266	} else {
267		len = ber_pvt_ber_write(ber);
268	}
269
270	sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n",
271		ber->ber_buf,
272		ber->ber_ptr,
273		ber->ber_end,
274		(long) len );
275
276	(void) (*ber_pvt_log_print)( buf );
277
278	ber_bprint( ber->ber_ptr, len );
279}
280
281typedef struct seqorset Seqorset;
282
283/* Exists for binary compatibility with OpenLDAP 2.4.17-- */
284int
285ber_log_sos_dump(
286	int errlvl,
287	int loglvl,
288	Seqorset *sos )
289{
290	return 0;
291}
292
293/* Exists for binary compatibility with OpenLDAP 2.4.17-- */
294void
295ber_sos_dump(
296	Seqorset *sos )
297{
298}
299