| #include "efence.h" | 
 | #include <signal.h> | 
 | #include <stdarg.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 |  | 
 | /* | 
 |  * These routines do their printing without using stdio. Stdio can't | 
 |  * be used because it calls malloc(). Internal routines of a malloc() | 
 |  * debugger should not re-enter malloc(), so stdio is out. | 
 |  */ | 
 |  | 
 | /* | 
 |  * NUMBER_BUFFER_SIZE is the longest character string that could be needed | 
 |  * to represent an unsigned integer, assuming we might print in base 2. | 
 |  */ | 
 | #define NUMBER_BUFFER_SIZE (sizeof(ef_number) * NBBY) | 
 |  | 
 | static void printNumber(ef_number number, ef_number base) | 
 | { | 
 | 	char buffer[NUMBER_BUFFER_SIZE]; | 
 | 	char *s = &buffer[NUMBER_BUFFER_SIZE]; | 
 | 	int size; | 
 |  | 
 | 	do { | 
 | 		ef_number digit; | 
 |  | 
 | 		if (--s == buffer) | 
 | 			EF_Abort("Internal error printing number."); | 
 |  | 
 | 		digit = number % base; | 
 |  | 
 | 		if (digit < 10) | 
 | 			*s = '0' + digit; | 
 | 		else | 
 | 			*s = 'a' + digit - 10; | 
 |  | 
 | 	} while ((number /= base) > 0); | 
 |  | 
 | 	size = &buffer[NUMBER_BUFFER_SIZE] - s; | 
 |  | 
 | 	if (size > 0) | 
 | 		write(2, s, size); | 
 | } | 
 |  | 
 | static void vprint(const char *pattern, va_list args) | 
 | { | 
 | 	static const char bad_pattern[] = | 
 | 	    "\nBad pattern specifier %%%c in EF_Print().\n"; | 
 | 	const char *s = pattern; | 
 | 	char c; | 
 |  | 
 | 	while ((c = *s++) != '\0') { | 
 | 		if (c == '%') { | 
 | 			c = *s++; | 
 | 			switch (c) { | 
 | 			case '%': | 
 | 				(void)write(2, &c, 1); | 
 | 				break; | 
 | 			case 'a': | 
 | 				/* | 
 | 				 * Print an address passed as a void pointer. | 
 | 				 * The type of ef_number must be set so that | 
 | 				 * it is large enough to contain all of the | 
 | 				 * bits of a void pointer. | 
 | 				 */ | 
 | 				printNumber((ef_number)va_arg(args, void *), | 
 | 					    0x10); | 
 | 				break; | 
 | 			case 's': { | 
 | 				const char *string; | 
 | 				size_t length; | 
 |  | 
 | 				string = va_arg(args, char *); | 
 | 				length = strlen(string); | 
 |  | 
 | 				(void)write(2, string, length); | 
 | 			} break; | 
 | 			case 'd': { | 
 | 				int n = va_arg(args, int); | 
 |  | 
 | 				if (n < 0) { | 
 | 					char c = '-'; | 
 | 					write(2, &c, 1); | 
 | 					n = -n; | 
 | 				} | 
 | 				printNumber(n, 10); | 
 | 			} break; | 
 | 			case 'x': | 
 | 				printNumber(va_arg(args, u_int), 0x10); | 
 | 				break; | 
 | 			case 'c': { | 
 | 			/*Cast used, since char gets promoted to int in ... */ | 
 | 				char c = (char)va_arg(args, int); | 
 |  | 
 | 				(void)write(2, &c, 1); | 
 | 			} break; | 
 | 			default: { | 
 | 				EF_Print(bad_pattern, c); | 
 | 			} | 
 | 			} | 
 | 		} else | 
 | 			(void)write(2, &c, 1); | 
 | 	} | 
 | } | 
 |  | 
 | void EF_Abort(const char *pattern, ...) | 
 | { | 
 | 	va_list args; | 
 |  | 
 | 	va_start(args, pattern); | 
 |  | 
 | 	EF_Print("\nElectricFence Aborting: "); | 
 | 	vprint(pattern, args); | 
 | 	EF_Print("\n"); | 
 |  | 
 | 	va_end(args); | 
 |  | 
 | 	/* | 
 | 	 * I use kill(getpid(), SIGILL) instead of abort() because some | 
 | 	 * mis-guided implementations of abort() flush stdio, which can | 
 | 	 * cause malloc() or free() to be called. | 
 | 	 */ | 
 | 	kill(getpid(), SIGILL); | 
 | 	/* Just in case something handles SIGILL and returns, exit here. */ | 
 | 	_exit(-1); | 
 | } | 
 |  | 
 | void EF_Exit(const char *pattern, ...) | 
 | { | 
 | 	va_list args; | 
 |  | 
 | 	va_start(args, pattern); | 
 |  | 
 | 	EF_Print("\nElectricFence Exiting: "); | 
 | 	vprint(pattern, args); | 
 | 	EF_Print("\n"); | 
 |  | 
 | 	va_end(args); | 
 |  | 
 | 	/* | 
 | 	 * I use _exit() because the regular exit() flushes stdio, | 
 | 	 * which may cause malloc() or free() to be called. | 
 | 	 */ | 
 | 	_exit(-1); | 
 | } | 
 |  | 
 | void EF_Print(const char *pattern, ...) | 
 | { | 
 | 	va_list args; | 
 |  | 
 | 	va_start(args, pattern); | 
 | 	vprint(pattern, args); | 
 | 	va_end(args); | 
 | } |