summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-04-12 13:57:36 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-04-12 13:57:36 +0200
commitcda663ab96252d0208078c0c61d3a71c1d3945da (patch)
tree503faf38ef629c496246e3833fc761de923fa326
parent8dc3c7b7693569ac83857e6fe5cdd9b09ebda7bd (diff)
downloadbiruda-cda663ab96252d0208078c0c61d3a71c1d3945da.tar.gz
biruda-cda663ab96252d0208078c0c61d3a71c1d3945da.tar.bz2
..
-rw-r--r--src/worker.c100
1 files changed, 68 insertions, 32 deletions
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 <string.h>
#include <strings.h>
#include <stdlib.h>
+#include <ctype.h>
#include <signal.h>
@@ -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;
}