summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODOS5
-rw-r--r--src/GNUmakefile5
-rw-r--r--src/biruda.c305
-rw-r--r--src/cli.c311
-rw-r--r--src/cli.h8
5 files changed, 323 insertions, 311 deletions
diff --git a/TODOS b/TODOS
index 8283f26..382f810 100644
--- a/TODOS
+++ b/TODOS
@@ -1,9 +1,4 @@
-- find ways to easy control subprocesses
- - glibc process
- - Poco
-
- links
-http://blog.borovsak.si/2009/07/spawning-processes-using-glib.html
http://www.codeguru.com/cpp/misc/misc/system/article.php/c8973/Determine-Windows-Version-and-Edition.htm
- surveyor -> bus, maybe also Windows blocking problem disappears
diff --git a/src/GNUmakefile b/src/GNUmakefile
index 3a574e2..b6d48e3 100644
--- a/src/GNUmakefile
+++ b/src/GNUmakefile
@@ -13,11 +13,11 @@ LIBS += `pkg-config --libs-only-l glib-2.0`
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
-biruda: biruda.o biruda_cmdline.o master.o coordinator.o worker.o system.o webserver.o 3rdParty/linenoise/linenoise.o 3rdParty/http_tiny/http_lib.o
+biruda: biruda.o biruda_cmdline.o master.o coordinator.o worker.o system.o webserver.o 3rdParty/linenoise/linenoise.o 3rdParty/http_tiny/http_lib.o cli.o
$(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
biruda_cmdline.o: biruda_cmdline.c
-biruda.o: biruda.c biruda_cmdline.h master.h coordinator.h worker.h port.h system.h webserver.h 3rdParty/linenoise/linenoise.h
+biruda.o: biruda.c biruda_cmdline.h master.h coordinator.h worker.h port.h system.h webserver.h 3rdParty/linenoise/linenoise.h cli.h
master.o: master.c master.h port.h
coordinator.o: coordinator.c coordinator.h port.h system.h
worker.o: worker.c worker.h port.h
@@ -25,6 +25,7 @@ system.o: system.c system.h
webserver.o: webserver.c webserver.h
3rdParty/linenoise/linenoise.o: 3rdParty/linenoise/linenoise.c 3rdParty/linenoise/linenoise.h
3rdParty/http_tiny/http_lib.o: 3rdParty/http_tiny/http_lib.c 3rdParty/http_tiny/http_lib.h
+cli.o: cli.c cli.h
biruda_cmdline.c: biruda.ggo
gengetopt -F biruda_cmdline --unamed-opts --conf-parser --include-getopt -i $<
diff --git a/src/biruda.c b/src/biruda.c
index ce49544..5f73aa5 100644
--- a/src/biruda.c
+++ b/src/biruda.c
@@ -31,13 +31,8 @@
#include "webserver.h"
#endif
-// for cli/interactive biruda client
#ifndef _WIN32
-#include <strings.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include "linenoise.h"
-#include "http_lib.h"
+#include "cli.h"
#endif
#include "port.h"
@@ -250,304 +245,6 @@ static void terminate_foreground_func( int sig )
}
#endif
-#ifndef _WIN32
-
-#define HISTORY_FILE ".biruda_history"
-
-typedef enum {
- COMMAND, // command parsing
- START_WORKER, // worker command expecting a worker parameter
- STOP_WORKER
-} command_state_t;
-
-static char *commands[] = {
- "help", "quit", "status", "start", "stop", NULL
-};
-
-static bool print_colors = false;
-
-static bool is_interactive = false;
-
-static command_state_t command_state = COMMAND;
-
-static char *worker_names[MAX_WORKERS];
-
-static int nof_worker_names = 0;
-
-static void cleanup_worker_names( )
-{
- for( int i = 0; i < nof_worker_names; i++ ) {
- free( worker_names[i] );
- }
- nof_worker_names = 0;
-}
-
-static void print_error( const char *fmt, ... );
-
-static void get_workers( )
-{
- char *url = "status";
- char *data = NULL;
- int len;
- http_retcode ret = http_get( url, &data, &len, NULL );
- if( ret == 200 ) {
- cleanup_worker_names( );
-
- char *line = strtok( data, "\n" );
- while( line != NULL ) {
- char *p = strchr( line, ' ' );
- if( p == NULL ) {
- line = strtok( NULL, "\n" );
- continue;
- }
- if( strncmp( line, "worker", p - line ) != 0 ) {
- line = strtok( NULL, "\n" );
- continue;
- }
- char *pp = strchr( p+1, ' ' );
- if( pp == NULL ) {
- line = strtok( NULL, "\n" );
- continue;
- }
- char s = *pp;
- *pp = '\0';
- if( nof_worker_names >= MAX_WORKERS ) {
- fprintf( stderr, "ERROR: Too many workers seen, ignoring rest!\n" );
- free( data );
- return;
- }
- worker_names[nof_worker_names++] = strdup( p + 1 );
- *pp = s;
- line = strtok( NULL, "\n" );
- }
- } else {
- print_error( "ERROR: HTTP error %d", ret );
- }
- free( data );
-}
-
-static void completion_func( const char *buf, linenoiseCompletions *lc )
-{
- unsigned int i;
- size_t len = strlen( buf );
-
- switch( command_state ) {
- case COMMAND:
- for (i = 0; commands[i]; ++i) {
- char *cmd = commands[i];
- if( strlen( cmd ) < len ) continue;
- if( strncasecmp( buf, cmd, len ) == 0 ) {
- linenoiseAddCompletion( lc, cmd );
- }
- }
- break;
-
- case START_WORKER:
- case STOP_WORKER:
- get_workers( );
- for( int i = 0; i < nof_worker_names; i++ ) {
- linenoiseAddCompletion( lc, worker_names[i] );
- }
- break;
- }
-}
-
-static void print_help( )
-{
- puts( "\n"
- " help - show this help page\n"
- " quit - quit the client\n"
- " status - status of the biruda network\n"
- " start - start a worker manually\n"
- " stop - stop a worker manually\n"
- );
-}
-
-static void print_colored( const char *fmt, int color, va_list ap )
-{
- char buf[1024];
-
- (void)vsnprintf( buf, sizeof( buf ), fmt, ap );
-
- if( print_colors ) {
- printf( "%c[9%dm%s%c[0m\n", 27, color, buf, 27 );
- } else {
- puts( buf );
- }
-}
-
-static void print_error( const char *fmt, ... )
-{
- va_list ap;
- va_start( ap, fmt );
- print_colored( fmt, 1, ap );
- va_end( ap );
-}
-
-static void print_answer( const char *fmt, ... )
-{
- va_list ap;
- va_start( ap, fmt );
- print_colored( fmt, 2, ap );
- va_end( ap );
-}
-
-static void print_status( )
-{
- char *url = "status";
- char *data = NULL;
- int len;
- http_retcode ret = http_get( url, &data, &len, NULL );
- if( ret == 200 ) {
- if( strlen( data ) > 0 && data[len-1] == '\n' ) {
- data[len-1] = '\0';
- len--;
- }
- if( strlen( data ) > 0 && data[len-1] == '\r' ) {
- data[len-1] = '\0';
- }
- print_answer( data );
- } else {
- print_error( "ERROR: HTTP error %d", ret );
- }
- free( data );
-}
-
-static void start_worker( const char *worker_name )
-{
- char url[128];
- snprintf( url, sizeof( url ), "worker?op=start&name=%s", worker_name );
- http_retcode ret = http_post( url, "", 0, "Content-Type: text/plain" );
- if( ret == 200 ) {
- print_answer( "Request queued" );
- } else {
- print_error( "ERROR: HTTP error %d", ret );
- }
-}
-
-static void stop_worker( const char *worker_name )
-{
- char url[128];
- snprintf( url, sizeof( url ), "worker?op=stop&name=%s", worker_name );
- http_retcode ret = http_post( url, "", 0, "Content-Type: text/plain" );
- if( ret == 200 ) {
- print_answer( "Request queued" );
- } else {
- print_error( "ERROR: HTTP error %d", ret );
- }
-}
-
-static int start_interactive( bool colors )
-{
- char history_filename[1024];
-
- // for http_tidy, tell it where to issue requests to
- http_server = "localhost";
- http_port = 8080;
-
- is_interactive = isatty( fileno( stdin ) );
- print_colors = is_interactive ? colors : false;
-
- if( is_interactive ) {
- char *home = getenv( "HOME" );
- if( home != NULL ) {
- snprintf( history_filename, sizeof( history_filename ), "%s/%s", home, HISTORY_FILE );
- linenoiseHistoryLoad( history_filename );
- linenoiseSetCompletionCallback( completion_func );
- }
- }
-
- char *context = "biruda";
- for( ;; ) {
- char prompt[128];
- char buf[1024];
- char *line;
-
- switch( command_state ) {
- case COMMAND:
- context = "biruda";
- break;
-
- case START_WORKER:
- case STOP_WORKER:
- context = "worker";
- break;
- }
-
- if( is_interactive ) {
- snprintf( prompt, sizeof( prompt ), "%s> ", context );
- if( ( line = linenoise( prompt ) ) == NULL ) {
- switch( command_state ) {
- case COMMAND:
- cleanup_worker_names( );
- free( line );
- return EXIT_SUCCESS;
-
- case START_WORKER:
- case STOP_WORKER:
- command_state = COMMAND;
- continue;
- }
- break;
- }
- strncpy( buf, line, sizeof( buf ) );
- free( line );
- line = buf;
- } else {
- if( fgets( buf, sizeof( buf ), stdin ) == NULL ) {
- cleanup_worker_names( );
- return EXIT_SUCCESS;
- }
- line = buf;
- }
-
- if( strlen( line ) > 1 ) {
- if( line[strlen( line )-1] == '\n' ) {
- line[strlen( line )-1] = '\0';
- }
- }
-
- if( is_interactive ) {
- linenoiseHistoryAdd( line );
- }
-
- switch( command_state ) {
- case COMMAND:
- if( strncasecmp( line, "quit", 4 ) == 0 ) {
- if( is_interactive ) {
- linenoiseHistorySave( history_filename );
- }
- cleanup_worker_names( );
- return EXIT_SUCCESS;
- } else if( strncasecmp( line, "help", 4 ) == 0 ) {
- print_help( );
- } else if( strncasecmp( line, "status", 6 ) == 0 ) {
- print_status( );
- } else if( strncasecmp( line, "start", 5 ) == 0 ) {
- command_state = START_WORKER;
- } else if( strncasecmp( line, "stop", 5 ) == 0 ) {
- command_state = STOP_WORKER;
- } else {
- print_error( "Bad command '%s'.", line );
- }
- break;
-
- case START_WORKER:
- start_worker( line );
- command_state = COMMAND;
- break;
-
- case STOP_WORKER:
- stop_worker( line );
- command_state = COMMAND;
- break;
- }
- }
-
- return EXIT_SUCCESS;
-}
-#endif
-
int main( int argc, char *argv[] )
{
struct gengetopt_args_info args_info;
diff --git a/src/cli.c b/src/cli.c
new file mode 100644
index 0000000..3f2e7fd
--- /dev/null
+++ b/src/cli.c
@@ -0,0 +1,311 @@
+#include "cli.h"
+
+#ifndef _WIN32
+#include <strings.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include "linenoise.h"
+#include "http_lib.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define HISTORY_FILE ".biruda_history"
+
+#include "coordinator.h"
+#include "worker.h"
+
+typedef enum {
+ COMMAND, // command parsing
+ START_WORKER, // worker command expecting a worker parameter
+ STOP_WORKER
+} command_state_t;
+
+static char *commands[] = {
+ "help", "quit", "status", "start", "stop", NULL
+};
+
+static bool print_colors = false;
+
+static bool is_interactive = false;
+
+static command_state_t command_state = COMMAND;
+
+static char *worker_names[MAX_WORKERS];
+
+static int nof_worker_names = 0;
+
+static void cleanup_worker_names( )
+{
+ for( int i = 0; i < nof_worker_names; i++ ) {
+ free( worker_names[i] );
+ }
+ nof_worker_names = 0;
+}
+
+static void print_error( const char *fmt, ... );
+
+static void get_workers( )
+{
+ char *url = "status";
+ char *data = NULL;
+ int len;
+ http_retcode ret = http_get( url, &data, &len, NULL );
+ if( ret == 200 ) {
+ cleanup_worker_names( );
+
+ char *line = strtok( data, "\n" );
+ while( line != NULL ) {
+ char *p = strchr( line, ' ' );
+ if( p == NULL ) {
+ line = strtok( NULL, "\n" );
+ continue;
+ }
+ if( strncmp( line, "worker", p - line ) != 0 ) {
+ line = strtok( NULL, "\n" );
+ continue;
+ }
+ char *pp = strchr( p+1, ' ' );
+ if( pp == NULL ) {
+ line = strtok( NULL, "\n" );
+ continue;
+ }
+ char s = *pp;
+ *pp = '\0';
+ if( nof_worker_names >= MAX_WORKERS ) {
+ fprintf( stderr, "ERROR: Too many workers seen, ignoring rest!\n" );
+ free( data );
+ return;
+ }
+ worker_names[nof_worker_names++] = strdup( p + 1 );
+ *pp = s;
+ line = strtok( NULL, "\n" );
+ }
+ } else {
+ print_error( "ERROR: HTTP error %d", ret );
+ }
+ free( data );
+}
+
+static void completion_func( const char *buf, linenoiseCompletions *lc )
+{
+ unsigned int i;
+ size_t len = strlen( buf );
+
+ switch( command_state ) {
+ case COMMAND:
+ for (i = 0; commands[i]; ++i) {
+ char *cmd = commands[i];
+ if( strlen( cmd ) < len ) continue;
+ if( strncasecmp( buf, cmd, len ) == 0 ) {
+ linenoiseAddCompletion( lc, cmd );
+ }
+ }
+ break;
+
+ case START_WORKER:
+ case STOP_WORKER:
+ get_workers( );
+ for( int i = 0; i < nof_worker_names; i++ ) {
+ linenoiseAddCompletion( lc, worker_names[i] );
+ }
+ break;
+ }
+}
+
+static void print_help( )
+{
+ puts( "\n"
+ " help - show this help page\n"
+ " quit - quit the client\n"
+ " status - status of the biruda network\n"
+ " start - start a worker manually\n"
+ " stop - stop a worker manually\n"
+ );
+}
+
+static void print_colored( const char *fmt, int color, va_list ap )
+{
+ char buf[1024];
+
+ (void)vsnprintf( buf, sizeof( buf ), fmt, ap );
+
+ if( print_colors ) {
+ printf( "%c[9%dm%s%c[0m\n", 27, color, buf, 27 );
+ } else {
+ puts( buf );
+ }
+}
+
+static void print_error( const char *fmt, ... )
+{
+ va_list ap;
+ va_start( ap, fmt );
+ print_colored( fmt, 1, ap );
+ va_end( ap );
+}
+
+static void print_answer( const char *fmt, ... )
+{
+ va_list ap;
+ va_start( ap, fmt );
+ print_colored( fmt, 2, ap );
+ va_end( ap );
+}
+
+static void print_status( )
+{
+ char *url = "status";
+ char *data = NULL;
+ int len;
+ http_retcode ret = http_get( url, &data, &len, NULL );
+ if( ret == 200 ) {
+ if( strlen( data ) > 0 && data[len-1] == '\n' ) {
+ data[len-1] = '\0';
+ len--;
+ }
+ if( strlen( data ) > 0 && data[len-1] == '\r' ) {
+ data[len-1] = '\0';
+ }
+ print_answer( data );
+ } else {
+ print_error( "ERROR: HTTP error %d", ret );
+ }
+ free( data );
+}
+
+static void start_worker( const char *worker_name )
+{
+ char url[128];
+ snprintf( url, sizeof( url ), "worker?op=start&name=%s", worker_name );
+ http_retcode ret = http_post( url, "", 0, "Content-Type: text/plain" );
+ if( ret == 200 ) {
+ print_answer( "Request queued" );
+ } else {
+ print_error( "ERROR: HTTP error %d", ret );
+ }
+}
+
+static void stop_worker( const char *worker_name )
+{
+ char url[128];
+ snprintf( url, sizeof( url ), "worker?op=stop&name=%s", worker_name );
+ http_retcode ret = http_post( url, "", 0, "Content-Type: text/plain" );
+ if( ret == 200 ) {
+ print_answer( "Request queued" );
+ } else {
+ print_error( "ERROR: HTTP error %d", ret );
+ }
+}
+
+int start_interactive( bool colors )
+{
+ char history_filename[1024];
+
+ // for http_tidy, tell it where to issue requests to
+ http_server = "localhost";
+ http_port = 8080;
+
+ is_interactive = isatty( fileno( stdin ) );
+ print_colors = is_interactive ? colors : false;
+
+ if( is_interactive ) {
+ char *home = getenv( "HOME" );
+ if( home != NULL ) {
+ snprintf( history_filename, sizeof( history_filename ), "%s/%s", home, HISTORY_FILE );
+ linenoiseHistoryLoad( history_filename );
+ linenoiseSetCompletionCallback( completion_func );
+ }
+ }
+
+ char *context = "biruda";
+ for( ;; ) {
+ char prompt[128];
+ char buf[1024];
+ char *line;
+
+ switch( command_state ) {
+ case COMMAND:
+ context = "biruda";
+ break;
+
+ case START_WORKER:
+ case STOP_WORKER:
+ context = "worker";
+ break;
+ }
+
+ if( is_interactive ) {
+ snprintf( prompt, sizeof( prompt ), "%s> ", context );
+ if( ( line = linenoise( prompt ) ) == NULL ) {
+ switch( command_state ) {
+ case COMMAND:
+ cleanup_worker_names( );
+ free( line );
+ return EXIT_SUCCESS;
+
+ case START_WORKER:
+ case STOP_WORKER:
+ command_state = COMMAND;
+ continue;
+ }
+ break;
+ }
+ strncpy( buf, line, sizeof( buf ) );
+ free( line );
+ line = buf;
+ } else {
+ if( fgets( buf, sizeof( buf ), stdin ) == NULL ) {
+ cleanup_worker_names( );
+ return EXIT_SUCCESS;
+ }
+ line = buf;
+ }
+
+ if( strlen( line ) > 1 ) {
+ if( line[strlen( line )-1] == '\n' ) {
+ line[strlen( line )-1] = '\0';
+ }
+ }
+
+ if( is_interactive ) {
+ linenoiseHistoryAdd( line );
+ }
+
+ switch( command_state ) {
+ case COMMAND:
+ if( strncasecmp( line, "quit", 4 ) == 0 ) {
+ if( is_interactive ) {
+ linenoiseHistorySave( history_filename );
+ }
+ cleanup_worker_names( );
+ return EXIT_SUCCESS;
+ } else if( strncasecmp( line, "help", 4 ) == 0 ) {
+ print_help( );
+ } else if( strncasecmp( line, "status", 6 ) == 0 ) {
+ print_status( );
+ } else if( strncasecmp( line, "start", 5 ) == 0 ) {
+ command_state = START_WORKER;
+ } else if( strncasecmp( line, "stop", 5 ) == 0 ) {
+ command_state = STOP_WORKER;
+ } else {
+ print_error( "Bad command '%s'.", line );
+ }
+ break;
+
+ case START_WORKER:
+ start_worker( line );
+ command_state = COMMAND;
+ break;
+
+ case STOP_WORKER:
+ stop_worker( line );
+ command_state = COMMAND;
+ break;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/cli.h b/src/cli.h
new file mode 100644
index 0000000..f362088
--- /dev/null
+++ b/src/cli.h
@@ -0,0 +1,8 @@
+#ifndef _BIRUDA_CLI_HEADER_INCLUDED
+#define _BIRUDA_CLI_HEADER_INCLUDED
+
+#include "port.h"
+
+int start_interactive( bool colors );
+
+#endif