From 0681152c5dc0c7eda6ec23ccd903188156b4b38c Mon Sep 17 00:00:00 2001
From: Hanoh Haim <hhaim@cisco.com>
Date: Tue, 14 Jun 2016 12:38:08 +0300
Subject: add ef code, not connected yet

---
 src/common/ef/print.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)
 create mode 100644 src/common/ef/print.cpp

(limited to 'src/common/ef/print.cpp')

diff --git a/src/common/ef/print.cpp b/src/common/ef/print.cpp
new file mode 100644
index 00000000..c28189e5
--- /dev/null
+++ b/src/common/ef/print.cpp
@@ -0,0 +1,170 @@
+#include "efence.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.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);
+}
-- 
cgit