Dial in the Makefile and command line option parsing. Better debug
authorMahlon E. Smith <mahlon@laika.com>
Sat, 03 Sep 2011 14:12:06 -0700
changeset 1 823d42546cea
parent 0 eac7211fe522
child 2 8c88756f81b0
Dial in the Makefile and command line option parsing. Better debug output.
Makefile
parser.rl
volta.c
volta.h
--- a/Makefile	Fri Aug 26 14:40:51 2011 -0700
+++ b/Makefile	Sat Sep 03 14:12:06 2011 -0700
@@ -1,25 +1,41 @@
 
-CFLAGS=-O2 -Wall
-CFLAGS_DEBUG=-Wall -DDEBUG -DPROG='"volta (debugmode)"'
-LIBS=-lsqlite3
+CFLAGS       = -O2
+LIBS         = -lsqlite3
+#OBJS         = $(patsubst %.c,%.o,$(wildcard *.c)) parser.o
+OBJS         =  volta.o parser.o
 
-volta: parser.c volta.c volta.h
-	$(CC) $(CFLAGS) $(LIBS) -o $@ *.c
+########################################################################
+### M A I N
+########################################################################
+
+volta: $(OBJS)
+	$(CC) $(CFLAGS) $(LIBS) -o $@ $(OBJS)
 	strip $@
 
+$(OBJS): volta.h
+
 parser.c: parser.rl
 	ragel -L -C -e -G2 parser.rl -o $@
 
-debug: volta_debug
+
+########################################################################
+### D E B U G
+########################################################################
 
-volta_debug: parser_debug.c volta.h
-	$(CC) $(CFLAGS_DEBUG) $(LIBS) -o volta *.c
+debug: CFLAGS = -Wall -DDEBUG -DPROG='"volta (debugmode)"'
+debug: volta parser_state.xml parser_state.png parser_state.dot
 
-parser_debug.c: parser.c
-	ragel -V parser.rl > parser_state.dot
-	ragel -C -e -G2 -V -x parser.rl -o parser_state.xml
+parser_state.xml parser_state.png parser_state.dot: parser.rl
+	ragel -Vp parser.rl > parser_state.dot
+	ragel -C -e -G2 -x parser.rl -o parser_state.xml
 	dot -Tpng parser_state.dot > parser_state.png
 
+
+########################################################################
+### U T I L
+########################################################################
+
+.PHONY : clean
 clean:
-	@rm -rf volta volta_debug* parser.c parser_state.*
+	-rm -f volta volta_debug* parser.c parser_state.* *.o
 
--- a/parser.rl	Fri Aug 26 14:40:51 2011 -0700
+++ b/parser.rl	Sat Sep 03 14:12:06 2011 -0700
@@ -2,7 +2,26 @@
 
 #include "volta.h"
 
+%%{
+	machine redirector;
+
+	action yay {
+		printf( "YAH\n" );
+	}
+
+	# http://, ftp://, https://, etc
+	proto = alpha{3,5} . '://';
+
+	# http://mahlon:password@example.com or http://mahlon@example.com
+    #       username              optional password
+	creds = ( alnum | [+._\-] )+ . ( ':' . any+ )? . '@';
+
+	main := ' ' @yay;
+}%%
+%% write data;
+
 /* state machine data */
+/*
 %%{
 	machine redirector;
 
@@ -20,6 +39,7 @@
 	main := ( proto . creds ) | proto @yay '\n';
 }%%
 %% write data;
+*/
 
 int
 parse( char *p )
@@ -28,8 +48,8 @@
 	short int cs = 0;
 
 	/* the client request object */
-	request c_request;
-	request *cp_request = &c_request;
+	/* request c_request; */
+	/* request *cp_request = &c_request; */
 
 	/*
 	char ip[ INET_ADDRSTRLEN ];
--- a/volta.c	Fri Aug 26 14:40:51 2011 -0700
+++ b/volta.c	Sat Sep 03 14:12:06 2011 -0700
@@ -1,6 +1,6 @@
 /* vim: set noet nosta sw=4 ts=4 ft=c : */
 /* Squid docs:
----------------------------------------------------------------------------
+   ---------------------------------------------------------------------------
 TAG: url_rewrite_program
 Specify the location of the executable for the URL rewriter.
 Since they can perform almost any function there isn't one included.
@@ -30,31 +30,74 @@
  * flush stdout on writes
  * empty struct not necessary?
  * inet_pton( AF_INET, *char src, dest )
+ * an option to run the DB out of memory?
+ * PRAGMA user_version = 1;
  *
  */
 
 #include "volta.h"
+#include <time.h>
+unsigned short int debugmode;
+
 
 int
 main( int argc, char *argv[] ) {
 
-	int opt;
+	/* opt action flags */
+	struct {
+		unsigned short int init;
+	} actions = {0};
 
-	/* storage for line received from squid */
-	char line[ LINE_BUFSIZE ];
+#ifdef DEBUG
+	/* debugmode set at compile time, default to display everything */
+	debugmode = 99;
+#else
+	debugmode = 0;
+#endif
+
+	/* get_opt vars */
+	int opt = 0;
+	opterr  = 0;
 
-	while ( (opt = getopt( argc, argv, "a:hv" )) != -1 ) {
+	/* parse options */
+	while ( (opt = getopt( argc, argv, "a:d:hv" )) != -1 ) {
 		switch ( opt ) {
+
+			/* action */
 			case 'a':
-				printf( "a -> '%s' (no-op at the moment)\n", optarg );
+				if ( strcmp( optarg, "init" ) == 0 ) actions.init++;
 				break;
+
+			/* debug */
+			case 'd':
+				if ( optarg[0] == '-' ) {
+					argc++; argv -= 1;
+					debugmode = 1;
+				}
+				sscanf( optarg, "%hu", &debugmode );
+				break;
+
+			/* help */
 			case 'h':
 				usage( argv[0] );
 				return( 0 );
+
+			/* version */
 			case 'v':
-				printf( "%s version %s\n", PROG, VERSION );
+				printf( "%s %s\n", PROG, VERSION );
 				return( 0 );
+
+			/* unknown option or option argument missing */
 			case '?':
+				switch( optopt ) {
+					case 'd': /* no debug argument, default to level 1 */
+						debugmode = 1;
+						break;
+					default:
+						usage( argv[0] );
+						return( 1 );
+				}
+
 			default:
 				break;
 		}
@@ -62,42 +105,66 @@
 	argc -= optind;
 	argv += optind;
 
-	/* start stdin line loop */
+	/* perform actions */
+	if ( actions.init ) {
+		debug( 1, LOC, "init! init! init!\n" );
+		return( 0 );
+	}
+
+	/* start stdin parsing loop */
+	char line[ LINE_BUFSIZE ];
+	debug( 1, LOC, "Waiting for input...\n" );
 	while( fgets( line, LINE_BUFSIZE, stdin ) != NULL ) parse( line );
 
 	/* stdin closed */
-    debug( "End of stream, shutting down.\n" );
-    return( 0 );
+	debug( 1, LOC, "End of stream, shutting down.\n" );
+	return( 0 );
 }
 
+
 /*
  * Basic usage
  */
 void
 usage( char *prg )
 {
-	printf( "%s [-vh] [-a <init>]\n", prg );
+	printf( "%s [-vh] [-d <level>] [-a <init>]\n", prg );
 	printf( "    -v Display version\n" );
+	printf( "    -d <level> Show debug information on stderr\n" );
 	printf( "    -h Usage (you're lookin' at it)\n" );
-	printf( "    -a Perform an action:\n" );
-	printf( "         init: Initialize a new database\n" );
+	printf( "    -a Perform an action, being one of:\n" );
+	printf( "         init: Initialize a new, empty database\n" );
 	printf( "\n" );
 	return;
 }
 
 
 /*
- * Debug function, only output to stderr if -DDEBUG set
+ * Debug function, only output to stderr if the debug level is
+ * equal or greated to the output level.
+ *
+ * 	level: The minimum debug level that must be set for the 
+ * 	       line to be logged.
+ * 	file:  The current code file that is emitting the log
+ * 	line:  The line number of the code file that is emitting the log
+ * 	... :  any printf style strings and formats that constitute the log message
  */
 void
-debug( const char *fmt, ... )
+debug( int level, char *file, int line, const char *fmt, ... )
 {
-    va_list args;
+	if ( debugmode < level ) return;
+
+	char timestamp[20];
+	time_t t = time( NULL );
+	struct tm *now = localtime( &t );
+	strftime( timestamp, 20, "%F %T", now );
+
+	va_list args;
 	va_start( args, fmt );
-#ifdef DEBUG
-	fprintf( stderr, "%s %d: ", PROG, getpid() );
+	fprintf( stderr, "%s [%s] #%d (%s:%04d): ", PROG, timestamp, getpid(), file, line );
 	vfprintf( stderr, fmt, args );
-#endif
 	va_end( args );
+
+	return;
 }
 
--- a/volta.h	Fri Aug 26 14:40:51 2011 -0700
+++ b/volta.h	Sat Sep 03 14:12:06 2011 -0700
@@ -12,17 +12,26 @@
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#include <time.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <sqlite3.h>
+
 
 /* Maximum length per line from Squid */
 #define LINE_BUFSIZE 2048
 
-/* URL <SP> client_ip "/" fqdn <SP> user <SP> method [<SP> kvpairs]<NL> */
+/* Aid debugging */
+#define LOC __FILE__, __LINE__
+/* Global debug toggle */
+extern unsigned short int debugmode;
+
+/* The parsed attributes from the request line, as given to us by squid.
+ * URL <SP> client_ip "/" fqdn <SP> user <SP> method [<SP> kvpairs]<NL> */
 typedef struct request {
 	char   *url;
 	char   *host;
@@ -36,9 +45,9 @@
 /* An "empty" request struct used for re-assignment */
 static const struct request reset_request;
 
-/* Prototypes */
+/* Function prototypes */
 void usage( char *prg );
-void debug( const char *fmt, ... );
+void debug( int level, char *file, int line, const char *fmt, ... );
 int  parse( char *p );
 
 #endif