Annotation of embedaddon/strongswan/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c, revision 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>