Annotation of embedaddon/ntp/ElectricFence/print.c, revision 1.1
1.1 ! misho 1: #include "efence.h"
! 2: #include <stdlib.h>
! 3: #include <unistd.h>
! 4: #include <stdarg.h>
! 5: #include <string.h>
! 6: #include <signal.h>
! 7:
! 8: /*
! 9: * These routines do their printing without using stdio. Stdio can't
! 10: * be used because it calls malloc(). Internal routines of a malloc()
! 11: * debugger should not re-enter malloc(), so stdio is out.
! 12: */
! 13:
! 14: /*
! 15: * NUMBER_BUFFER_SIZE is the longest character string that could be needed
! 16: * to represent an unsigned integer, assuming we might print in base 2.
! 17: */
! 18: #define NUMBER_BUFFER_SIZE (sizeof(ef_number) * NBBY)
! 19:
! 20: static void
! 21: printNumber(ef_number number, ef_number base)
! 22: {
! 23: char buffer[NUMBER_BUFFER_SIZE];
! 24: char * s = &buffer[NUMBER_BUFFER_SIZE];
! 25: int size;
! 26:
! 27: do {
! 28: ef_number digit;
! 29:
! 30: if ( --s == buffer )
! 31: EF_Abort("Internal error printing number.");
! 32:
! 33: digit = number % base;
! 34:
! 35: if ( digit < 10 )
! 36: *s = '0' + digit;
! 37: else
! 38: *s = 'a' + digit - 10;
! 39:
! 40: } while ( (number /= base) > 0 );
! 41:
! 42: size = &buffer[NUMBER_BUFFER_SIZE] - s;
! 43:
! 44: if ( size > 0 )
! 45: write(2, s, size);
! 46: }
! 47:
! 48: static void
! 49: vprint(const char * pattern, va_list args)
! 50: {
! 51: static const char bad_pattern[] =
! 52: "\nBad pattern specifier %%%c in EF_Print().\n";
! 53: const char * s = pattern;
! 54: char c;
! 55:
! 56: while ( (c = *s++) != '\0' ) {
! 57: if ( c == '%' ) {
! 58: c = *s++;
! 59: switch ( c ) {
! 60: case '%':
! 61: (void) write(2, &c, 1);
! 62: break;
! 63: case 'a':
! 64: /*
! 65: * Print an address passed as a void pointer.
! 66: * The type of ef_number must be set so that
! 67: * it is large enough to contain all of the
! 68: * bits of a void pointer.
! 69: */
! 70: printNumber(
! 71: (ef_number)va_arg(args, void *)
! 72: ,0x10);
! 73: break;
! 74: case 's':
! 75: {
! 76: const char * string;
! 77: size_t length;
! 78:
! 79: string = va_arg(args, char *);
! 80: length = strlen(string);
! 81:
! 82: (void) write(2, string, length);
! 83: }
! 84: break;
! 85: case 'd':
! 86: {
! 87: int n = va_arg(args, int);
! 88:
! 89: if ( n < 0 ) {
! 90: char c = '-';
! 91: write(2, &c, 1);
! 92: n = -n;
! 93: }
! 94: printNumber(n, 10);
! 95: }
! 96: break;
! 97: case 'x':
! 98: printNumber(va_arg(args, u_int), 0x10);
! 99: break;
! 100: case 'c':
! 101: {
! 102: char c = va_arg(args, char);
! 103:
! 104: (void) write(2, &c, 1);
! 105: }
! 106: break;
! 107: default:
! 108: {
! 109: EF_Print(bad_pattern, c);
! 110: }
! 111:
! 112: }
! 113: }
! 114: else
! 115: (void) write(2, &c, 1);
! 116: }
! 117: }
! 118:
! 119: void
! 120: EF_Abort(const char * pattern, ...)
! 121: {
! 122: va_list args;
! 123:
! 124: va_start(args, pattern);
! 125:
! 126: EF_Print("\nElectricFence Aborting: ");
! 127: vprint(pattern, args);
! 128: EF_Print("\n");
! 129:
! 130: va_end(args);
! 131:
! 132: /*
! 133: * I use kill(getpid(), SIGILL) instead of abort() because some
! 134: * mis-guided implementations of abort() flush stdio, which can
! 135: * cause malloc() or free() to be called.
! 136: */
! 137: kill(getpid(), SIGILL);
! 138: /* Just in case something handles SIGILL and returns, exit here. */
! 139: _exit(-1);
! 140: }
! 141:
! 142: void
! 143: EF_Exit(const char * pattern, ...)
! 144: {
! 145: va_list args;
! 146:
! 147: va_start(args, pattern);
! 148:
! 149: EF_Print("\nElectricFence Exiting: ");
! 150: vprint(pattern, args);
! 151: EF_Print("\n");
! 152:
! 153: va_end(args);
! 154:
! 155: /*
! 156: * I use _exit() because the regular exit() flushes stdio,
! 157: * which may cause malloc() or free() to be called.
! 158: */
! 159: _exit(-1);
! 160: }
! 161:
! 162: void
! 163: EF_Print(const char * pattern, ...)
! 164: {
! 165: va_list args;
! 166:
! 167: va_start(args, pattern);
! 168: vprint(pattern, args);
! 169: va_end(args);
! 170: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>