Dial in the Makefile and command line option parsing. Better debug
output.
--- 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