Annotation of embedaddon/strongswan/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2009-2013 Tobias Brunner
3: * Copyright (C) 2006-2008 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "printf_hook.h"
18:
19: #include <utils/utils.h>
20: #include <utils/debug.h>
21:
22: #include <stdio.h>
23: #include <stdarg.h>
24: #include <string.h>
25: #include <printf.h>
26:
27: typedef struct private_printf_hook_t private_printf_hook_t;
28: typedef struct printf_hook_handler_t printf_hook_handler_t;
29:
30: /**
31: * private data of printf_hook
32: */
33: struct private_printf_hook_t {
34:
35: /**
36: * public functions
37: */
38: printf_hook_t public;
39: };
40:
41: /**
42: * struct with information about a registered handler
43: */
44: struct printf_hook_handler_t {
45:
46: /**
47: * callback function
48: */
49: printf_hook_function_t hook;
50:
51: /**
52: * number of arguments
53: */
54: int numargs;
55:
56: /**
57: * types of the arguments, PA_*
58: */
59: int argtypes[3];
60: };
61:
62: /**
63: * Data to pass to a printf hook.
64: */
65: struct printf_hook_data_t {
66:
67: /**
68: * Output FILE stream
69: */
70: FILE *stream;;
71: };
72:
73: /* A-Z | 6 other chars | a-z */
74: static printf_hook_handler_t *printf_hooks[58];
75:
76: #define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
77:
78: /**
79: * Glibc variant of print_in_hook()
80: */
81: size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...)
82: {
83: ssize_t written;
84: va_list args;
85:
86: va_start(args, fmt);
87: written = vfprintf(data->stream, fmt, args);
88: va_end(args);
89:
90: if (written < 0)
91: {
92: written = 0;
93: }
94: return written;
95: }
96:
97: /**
98: * Printf hook print function. This is actually of type "printf_function",
99: * however glibc does it typedef to function, but uclibc to a pointer.
100: * So we redefine it here.
101: */
102: static int custom_print(FILE *stream, const struct printf_info *info,
103: const void *const *args)
104: {
105: printf_hook_spec_t spec;
106: printf_hook_handler_t *handler;
107: printf_hook_data_t data = {
108: .stream = stream,
109: };
110:
111: handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
112: spec.hash = info->alt;
113: spec.plus = info->showsign;
114: spec.minus = info->left;
115: spec.width = info->width;
116:
117: return handler->hook(&data, &spec, args);
118: }
119:
120: /**
121: * Printf hook arginfo function, which is actually of type
122: * "printf_arginfo_[size_]function".
123: */
124: static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes
125: #ifdef HAVE_PRINTF_SPECIFIER
126: , int *size
127: #endif
128: )
129: {
130: int i;
131: printf_hook_handler_t *handler;
132:
133: handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
134: if (handler->numargs <= n)
135: {
136: for (i = 0; i < handler->numargs; ++i)
137: {
138: argtypes[i] = handler->argtypes[i];
139: }
140: }
141: /* we never set "size", as we have no user defined types */
142: return handler->numargs;
143: }
144:
145: METHOD(printf_hook_t, add_handler, void,
146: private_printf_hook_t *this, char spec,
147: printf_hook_function_t hook, ...)
148: {
149: int i = -1;
150: bool failed = FALSE;
151: printf_hook_handler_t *handler;
152: printf_hook_argtype_t argtype;
153: va_list args;
154:
155: if (SPEC_TO_INDEX(spec) <= -1 ||
156: SPEC_TO_INDEX(spec) >= countof(printf_hooks))
157: {
158: DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
159: "not registered!", spec);
160: return;
161: }
162:
163: INIT(handler,
164: .hook = hook,
165: );
166:
167: va_start(args, hook);
168: while (!failed)
169: {
170: argtype = va_arg(args, printf_hook_argtype_t);
171:
172: if (argtype == PRINTF_HOOK_ARGTYPE_END)
173: {
174: break;
175: }
176: if (++i >= countof(handler->argtypes))
177: {
178: DBG1(DBG_LIB, "Too many arguments for printf hook with "
179: "specifier '%c', not registered!", spec);
180: failed = TRUE;
181: break;
182: }
183: switch (argtype)
184: {
185: case PRINTF_HOOK_ARGTYPE_INT:
186: handler->argtypes[i] = PA_INT;
187: break;
188: case PRINTF_HOOK_ARGTYPE_POINTER:
189: handler->argtypes[i] = PA_POINTER;
190: break;
191: default:
192: DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec);
193: failed = TRUE;
194: break;
195: }
196: }
197: va_end(args);
198:
199: handler->numargs = i + 1;
200: if (!failed && handler->numargs > 0)
201: {
202: # ifdef HAVE_PRINTF_SPECIFIER
203: register_printf_specifier(spec, custom_print, custom_arginfo);
204: # else
205: register_printf_function(spec, custom_print, custom_arginfo);
206: # endif
207: printf_hooks[SPEC_TO_INDEX(spec)] = handler;
208: }
209: else
210: {
211: free(handler);
212: }
213: }
214:
215: METHOD(printf_hook_t, destroy, void,
216: private_printf_hook_t *this)
217: {
218: int i;
219:
220: for (i = 0; i < countof(printf_hooks); i++)
221: {
222: free(printf_hooks[i]);
223: }
224: free(this);
225: }
226:
227: /*
228: * see header file
229: */
230: printf_hook_t *printf_hook_create()
231: {
232: private_printf_hook_t *this;
233:
234: INIT(this,
235: .public = {
236: .add_handler = _add_handler,
237: .destroy = _destroy,
238: },
239: );
240:
241: memset(printf_hooks, 0, sizeof(printf_hooks));
242:
243: return &this->public;
244: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>