From cda663ab96252d0208078c0c61d3a71c1d3945da Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 12 Apr 2015 13:57:36 +0200 Subject: .. --- src/worker.c | 100 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/worker.c b/src/worker.c index 7807697..c73eb7e 100644 --- a/src/worker.c +++ b/src/worker.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -259,78 +260,113 @@ static gboolean watch_output( GIOChannel *channel, GIOCondition condition, gpoin static char *expand_system_variables( const char *s ) { - char *r = (char *)malloc( strlen( s ) * 2 ); + size_t r_size = strlen( s ) * 2; + char *r = (char *)malloc( r_size ); char *d = r; - bool var_begin = false; - bool in_var = false; + enum { COPYING, DOLLAR, OPEN_BRACE, VARIABLE, CLOSE_BRACE, ERROR } state = COPYING; const char *var = NULL; const char *p = s; - while( *p != '\0' && d - r < strlen( s ) * 2 - 1 ) { - switch( *p ) { - case '$': - var_begin = true; + while( state != ERROR && *p != '\0' && d - r < r_size - 1 ) { + switch( state ) { + case COPYING: + if( *p == '$' ) { + state = DOLLAR; + p++; + } else { + *d = *p; + d++; + p++; + } break; - case '{': - if( var_begin ) { - in_var = true; - var = p + 1; + case DOLLAR: + if( *p == '{' ) { + state = OPEN_BRACE; + p++; } else { - fprintf( stderr, "ERROR: Unexpected '{' at position %d in '%s'\n", p-s, s ); - free( r ); - return NULL; + fprintf( stderr, "ERROR: Unexpected '{' at position %d in '%s'\n", (int)( p - s ), s ); + state = ERROR; } break; - - case '}': - if( var_begin ) { - fprintf( stderr, "ERROR: Empty variable declaration '${}' at position %d in '%s'\n", p-s, s ); - free( r ); - return NULL; + + case OPEN_BRACE: + if( *p == '}' ) { + fprintf( stderr, "ERROR: Empty variable declaration '${}' at position %d in '%s'\n", (int)( p - s ), s ); + state = ERROR; + p++; + } else if( isalpha( *p ) ) { + // ok, part of variable name + state = VARIABLE; + var = p; + p++; + } else { + fprintf( stderr, "ERROR: Illegal character '%c' at position %d in variable in '%s'\n", *p, (int)( p - s ), s ); + state = ERROR; } - in_var = false; - var_begin = false; + break; + + case VARIABLE: + if( *p == '}' ) { + state = CLOSE_BRACE; + } else if( isalpha( *p ) ) { + // ok, part of variable name + p++; + } else { + fprintf( stderr, "ERROR: Illegal character '%c' at position %d in variable in '%s'\n", *p, (int)( p - s ), s ); + state = ERROR; + } + break; + + case CLOSE_BRACE: if( strncmp( var, "ARCH", 4 ) == 0 ) { char machine_arch[100]; system_arch( machine_arch, sizeof( machine_arch ) ); strncpy( d, machine_arch, strlen( machine_arch ) ); d += strlen( machine_arch ); + state = COPYING; } else if( strncmp( var, "OS", 2 ) == 0 ) { char os_name[100]; system_os( os_name, sizeof( os_name ) ); strncpy( d, os_name, strlen( os_name ) ); d += strlen( os_name ); + state = COPYING; } else if( strncmp( var, "HOST", 4 ) == 0 ) { char hostname[100]; gethostname( hostname, sizeof( hostname ) ); strncpy( d, hostname, strlen( hostname ) ); d += strlen( hostname ); + state = COPYING; } else if( strncmp( var, "CPUS", 4 ) == 0 ) { unsigned int nofCpus = system_available_cpus( ); char buf[10]; snprintf( buf, sizeof( buf ), "%d", nofCpus ); strncpy( d, buf, strlen( buf ) ); d += strlen( buf ); + state = COPYING; } else { - fprintf( stderr, "ERROR: Unknown variable '${%*s}' at position %d in '%s'\n", p-var, var, p-s, s ); - free( r ); - return NULL; + fprintf( stderr, "ERROR: Unknown variable '${%*s}' at position %d in '%s'\n", (int)( p-var ), var, (int)( p - s ), s ); + state = ERROR; } + p++; break; + case ERROR: default: - if( in_var ) { - var_begin = false; - } else { - *d = *p; - d++; - } + break; } - p++; } *d = '\0'; + if( d - r >= r_size - 1 ) { + fprintf( stderr, "ERROR: out of memory while substituting variables in '%s'\n", s ); + state = ERROR; + } + + if( state == ERROR ) { + return NULL; + } + return r; } -- cgit v1.2.3-54-g00ecf