Return to printf_hook_glibc.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / utils / printf_hook |
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: }