Fossil SCM
Simplify the implementation of the --args FILENAME patch, as requested by the FIXME comment.
Commit
eb8d989daebfce1fd22513bb3718b25bd572e86a
Parent
8a6568c3a32521c…
1 file changed
+55
-133
+55
-133
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -232,142 +232,64 @@ | ||
| 232 | 232 | } |
| 233 | 233 | return 1+(cnt>1); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | 236 | /* |
| 237 | -** Reads all non-empty lines of the given file and replaces g.argv | |
| 238 | -** with their contents. argsPos is the position of the --args | |
| 239 | -** parameter, and zFile is assumed to be the argument immediately | |
| 240 | -** following g.argv[argsPos]. | |
| 241 | -** | |
| 242 | -** FIXME: this impl is certainly way too complicated. | |
| 243 | -*/ | |
| 244 | -static void read_args_lines(unsigned int argsPos, char const * zFile){ | |
| 245 | - Blob buffer = empty_blob; | |
| 246 | - Blob line = empty_blob; | |
| 247 | - typedef struct StringList { | |
| 248 | - char * str; | |
| 249 | - struct StringList * next; | |
| 250 | - } StringList; | |
| 251 | - StringList * head = NULL; | |
| 252 | - StringList * current = NULL; | |
| 253 | - FILE * infile; | |
| 254 | - int blobSize = 0; | |
| 255 | - unsigned int lineCount = 0; | |
| 256 | - unsigned int i = 0; | |
| 257 | - assert(argsPos>=1); | |
| 258 | - assert(g.argc>=(argsPos+1)); | |
| 259 | - assert(0==strcmp(zFile,g.argv[argsPos+1])); | |
| 260 | - infile = fopen(zFile,"rb"); | |
| 261 | - if(!infile){ | |
| 262 | - fossil_panic("Could not open file [%s].",zFile); | |
| 263 | - } | |
| 264 | - blob_read_from_channel(&buffer,infile,-1); | |
| 265 | - fclose(infile); | |
| 266 | - blobSize = blob_size(&buffer); | |
| 267 | - if(blobSize<=0){ | |
| 268 | - /* FIXME? error here? */ | |
| 269 | - blob_reset(&buffer); | |
| 270 | - return; | |
| 271 | - } | |
| 272 | - blob_rewind(&buffer); | |
| 273 | - while(1){ | |
| 274 | - int lineLen = blob_line(&buffer,&line); | |
| 275 | - StringList * next = NULL; | |
| 276 | - if(0==lineLen){ | |
| 277 | - break; | |
| 278 | - } | |
| 279 | - else if(lineLen<2){ | |
| 280 | - continue; /* ignore empty lines */ | |
| 281 | - } | |
| 282 | - next = (StringList*)calloc(1,sizeof(StringList)); | |
| 283 | - ++lineCount; | |
| 284 | - if( !head ) { | |
| 285 | - head = next; | |
| 286 | - } | |
| 287 | - if( current ){ | |
| 288 | - current->next = next; | |
| 289 | - current = next; | |
| 290 | - }else{ | |
| 291 | - assert(head==next); | |
| 292 | - current = head; | |
| 293 | - } | |
| 294 | - current->str = strdup(blob_buffer(&line)); | |
| 295 | - current->str[lineLen-1] = 0/*replace \n with NULL. FIXME: strip \r as well.*/; | |
| 296 | - blob_reset(&line); | |
| 297 | - } | |
| 298 | - blob_reset(&buffer); | |
| 299 | - if(lineCount){ | |
| 300 | - int const newArgc = g.argc + lineCount - 2; | |
| 301 | - unsigned int i; | |
| 302 | - unsigned int argOffset = 0; | |
| 303 | - char ** newArgv = calloc(newArgc,sizeof(char*)); | |
| 304 | - assert(NULL != newArgv); | |
| 305 | - for(i = 0; i < argsPos; ++i){ | |
| 306 | - newArgv[i] = g.argv[i]; | |
| 307 | - } | |
| 308 | - argOffset = i; | |
| 309 | - current = head; | |
| 310 | - for( i = 0; i < lineCount; ++i, ++argOffset ){ | |
| 311 | - StringList * toFree = current; | |
| 312 | - assert(NULL != current); | |
| 313 | - assert(NULL != current->str); | |
| 314 | - newArgv[argOffset] = current->str; | |
| 315 | - current = current->next; | |
| 316 | - free(toFree); | |
| 317 | - } | |
| 318 | - /* FIXME: to simplify the code we move the --args args AFTER all | |
| 319 | - others. This is, however, arguablly very wrong. We should | |
| 320 | - instead insert them in place of --args XYZ. | |
| 321 | - */ | |
| 322 | - for(i = argsPos+2; i < g.argc; ++i, ++argOffset){ | |
| 323 | - newArgv[argOffset] = g.argv[i]; | |
| 324 | - } | |
| 325 | - assert(NULL==current); | |
| 326 | - g.argc = newArgc; | |
| 327 | - g.argv = newArgv; | |
| 328 | - } | |
| 329 | -#if 0 | |
| 330 | - { | |
| 331 | - int i; | |
| 332 | - printf("g.argc=%d\n",g.argc); | |
| 333 | - for( i = 0; i < g.argc; ++i ){ | |
| 334 | - printf("g.argv[%d] = %s\n",i, g.argv[i]); | |
| 335 | - } | |
| 336 | - } | |
| 337 | -#endif | |
| 338 | -} | |
| 339 | - | |
| 340 | - | |
| 341 | -/* | |
| 342 | -** Reads the --args FILENAME CLI option and massages g.argc/g.argv | |
| 343 | -*/ | |
| 344 | -static void expand_args_arg(){ | |
| 345 | - assert((g.argc>0) && g.argv[g.argc-1]); | |
| 346 | - if(g.argc<3){ | |
| 347 | - return; | |
| 348 | - }else{ | |
| 349 | - unsigned int i = 1; | |
| 350 | - char got = 0; | |
| 351 | - for( ; i < (unsigned int)g.argc; ++i ){ | |
| 352 | - if(0==strcmp("--args",g.argv[i])){ | |
| 353 | - got = 1; | |
| 354 | - break; | |
| 355 | - } | |
| 356 | - } | |
| 357 | - if(!got){ | |
| 358 | - return; | |
| 359 | - }else{ | |
| 360 | - char const * zFile; | |
| 361 | - if(i==(g.argc-1)){ | |
| 362 | - /* FIXME: error out/exit here. Missing filename. */ | |
| 363 | - return; | |
| 364 | - } | |
| 365 | - zFile = g.argv[i+1]; | |
| 366 | - read_args_lines(i,zFile); | |
| 367 | - } | |
| 368 | - } | |
| 237 | +** Search g.argv for arguments "--args FILENAME". If found, then | |
| 238 | +** (1) remove the two arguments from g.argv | |
| 239 | +** (2) Read the file FILENAME | |
| 240 | +** (3) Use the contents of FILE to replace the two removed arguments: | |
| 241 | +** (a) Ignore blank lines in the file | |
| 242 | +** (b) Each non-empty line of the file is an argument, except | |
| 243 | +** (c) If the line begins with "-" and contains a space, it is broken | |
| 244 | +** into two arguments at the space. | |
| 245 | +*/ | |
| 246 | +static void expand_args_option(void){ | |
| 247 | + Blob file = empty_blob; /* Content of the file */ | |
| 248 | + Blob line = empty_blob; /* One line of the file */ | |
| 249 | + unsigned int nLine; /* Number of lines in the file*/ | |
| 250 | + unsigned int i, j, k; /* Loop counters */ | |
| 251 | + int n; /* Number of bytes in one line */ | |
| 252 | + char *z; /* General use string pointer */ | |
| 253 | + char **newArgv; /* New expanded g.argv under construction */ | |
| 254 | + | |
| 255 | + for(i=1; i<g.argc-1; i++){ | |
| 256 | + z = g.argv[i]; | |
| 257 | + if( z[0]!='-' ) continue; | |
| 258 | + z++; | |
| 259 | + if( z[0]=='-' ) z++; | |
| 260 | + if( z[0]==0 ) return; /* Stop searching at "--" */ | |
| 261 | + if( fossil_strcmp(z, "args")==0 ) break; | |
| 262 | + } | |
| 263 | + if( i>=g.argc-1 ) return; | |
| 264 | + | |
| 265 | + blob_read_from_file(&file, g.argv[i+1]); | |
| 266 | + z = blob_str(&file); | |
| 267 | + for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++; | |
| 268 | + newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) ); | |
| 269 | + for(j=0; j<i; j++) newArgv[j] = g.argv[j]; | |
| 270 | + | |
| 271 | + blob_rewind(&file); | |
| 272 | + while( (n = blob_line(&file, &line))>0 ){ | |
| 273 | + if( n<=1 ) continue; | |
| 274 | + z = blob_buffer(&line); | |
| 275 | + z[n-1] = 0; | |
| 276 | + newArgv[j++] = z; | |
| 277 | + if( z[0]=='-' ){ | |
| 278 | + for(k=1; z[k] && !fossil_isspace(z[k]); k++){} | |
| 279 | + if( z[k] ){ | |
| 280 | + z[k] = 0; | |
| 281 | + k++; | |
| 282 | + if( z[k] ) newArgv[j++] = &z[k]; | |
| 283 | + } | |
| 284 | + } | |
| 285 | + } | |
| 286 | + i += 2; | |
| 287 | + while( i<g.argc ) newArgv[j++] = g.argv[i++]; | |
| 288 | + newArgv[j] = 0; | |
| 289 | + g.argc = j; | |
| 290 | + g.argv = newArgv; | |
| 369 | 291 | } |
| 370 | 292 | |
| 371 | 293 | /* |
| 372 | 294 | ** This procedure runs first. |
| 373 | 295 | */ |
| @@ -379,11 +301,11 @@ | ||
| 379 | 301 | |
| 380 | 302 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 381 | 303 | g.now = time(0); |
| 382 | 304 | g.argc = argc; |
| 383 | 305 | g.argv = argv; |
| 384 | - expand_args_arg(); | |
| 306 | + expand_args_option(); | |
| 385 | 307 | argc = g.argc; |
| 386 | 308 | argv = g.argv; |
| 387 | 309 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 388 | 310 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| 389 | 311 | zCmdName = "cgi"; |
| 390 | 312 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -232,142 +232,64 @@ | |
| 232 | } |
| 233 | return 1+(cnt>1); |
| 234 | } |
| 235 | |
| 236 | /* |
| 237 | ** Reads all non-empty lines of the given file and replaces g.argv |
| 238 | ** with their contents. argsPos is the position of the --args |
| 239 | ** parameter, and zFile is assumed to be the argument immediately |
| 240 | ** following g.argv[argsPos]. |
| 241 | ** |
| 242 | ** FIXME: this impl is certainly way too complicated. |
| 243 | */ |
| 244 | static void read_args_lines(unsigned int argsPos, char const * zFile){ |
| 245 | Blob buffer = empty_blob; |
| 246 | Blob line = empty_blob; |
| 247 | typedef struct StringList { |
| 248 | char * str; |
| 249 | struct StringList * next; |
| 250 | } StringList; |
| 251 | StringList * head = NULL; |
| 252 | StringList * current = NULL; |
| 253 | FILE * infile; |
| 254 | int blobSize = 0; |
| 255 | unsigned int lineCount = 0; |
| 256 | unsigned int i = 0; |
| 257 | assert(argsPos>=1); |
| 258 | assert(g.argc>=(argsPos+1)); |
| 259 | assert(0==strcmp(zFile,g.argv[argsPos+1])); |
| 260 | infile = fopen(zFile,"rb"); |
| 261 | if(!infile){ |
| 262 | fossil_panic("Could not open file [%s].",zFile); |
| 263 | } |
| 264 | blob_read_from_channel(&buffer,infile,-1); |
| 265 | fclose(infile); |
| 266 | blobSize = blob_size(&buffer); |
| 267 | if(blobSize<=0){ |
| 268 | /* FIXME? error here? */ |
| 269 | blob_reset(&buffer); |
| 270 | return; |
| 271 | } |
| 272 | blob_rewind(&buffer); |
| 273 | while(1){ |
| 274 | int lineLen = blob_line(&buffer,&line); |
| 275 | StringList * next = NULL; |
| 276 | if(0==lineLen){ |
| 277 | break; |
| 278 | } |
| 279 | else if(lineLen<2){ |
| 280 | continue; /* ignore empty lines */ |
| 281 | } |
| 282 | next = (StringList*)calloc(1,sizeof(StringList)); |
| 283 | ++lineCount; |
| 284 | if( !head ) { |
| 285 | head = next; |
| 286 | } |
| 287 | if( current ){ |
| 288 | current->next = next; |
| 289 | current = next; |
| 290 | }else{ |
| 291 | assert(head==next); |
| 292 | current = head; |
| 293 | } |
| 294 | current->str = strdup(blob_buffer(&line)); |
| 295 | current->str[lineLen-1] = 0/*replace \n with NULL. FIXME: strip \r as well.*/; |
| 296 | blob_reset(&line); |
| 297 | } |
| 298 | blob_reset(&buffer); |
| 299 | if(lineCount){ |
| 300 | int const newArgc = g.argc + lineCount - 2; |
| 301 | unsigned int i; |
| 302 | unsigned int argOffset = 0; |
| 303 | char ** newArgv = calloc(newArgc,sizeof(char*)); |
| 304 | assert(NULL != newArgv); |
| 305 | for(i = 0; i < argsPos; ++i){ |
| 306 | newArgv[i] = g.argv[i]; |
| 307 | } |
| 308 | argOffset = i; |
| 309 | current = head; |
| 310 | for( i = 0; i < lineCount; ++i, ++argOffset ){ |
| 311 | StringList * toFree = current; |
| 312 | assert(NULL != current); |
| 313 | assert(NULL != current->str); |
| 314 | newArgv[argOffset] = current->str; |
| 315 | current = current->next; |
| 316 | free(toFree); |
| 317 | } |
| 318 | /* FIXME: to simplify the code we move the --args args AFTER all |
| 319 | others. This is, however, arguablly very wrong. We should |
| 320 | instead insert them in place of --args XYZ. |
| 321 | */ |
| 322 | for(i = argsPos+2; i < g.argc; ++i, ++argOffset){ |
| 323 | newArgv[argOffset] = g.argv[i]; |
| 324 | } |
| 325 | assert(NULL==current); |
| 326 | g.argc = newArgc; |
| 327 | g.argv = newArgv; |
| 328 | } |
| 329 | #if 0 |
| 330 | { |
| 331 | int i; |
| 332 | printf("g.argc=%d\n",g.argc); |
| 333 | for( i = 0; i < g.argc; ++i ){ |
| 334 | printf("g.argv[%d] = %s\n",i, g.argv[i]); |
| 335 | } |
| 336 | } |
| 337 | #endif |
| 338 | } |
| 339 | |
| 340 | |
| 341 | /* |
| 342 | ** Reads the --args FILENAME CLI option and massages g.argc/g.argv |
| 343 | */ |
| 344 | static void expand_args_arg(){ |
| 345 | assert((g.argc>0) && g.argv[g.argc-1]); |
| 346 | if(g.argc<3){ |
| 347 | return; |
| 348 | }else{ |
| 349 | unsigned int i = 1; |
| 350 | char got = 0; |
| 351 | for( ; i < (unsigned int)g.argc; ++i ){ |
| 352 | if(0==strcmp("--args",g.argv[i])){ |
| 353 | got = 1; |
| 354 | break; |
| 355 | } |
| 356 | } |
| 357 | if(!got){ |
| 358 | return; |
| 359 | }else{ |
| 360 | char const * zFile; |
| 361 | if(i==(g.argc-1)){ |
| 362 | /* FIXME: error out/exit here. Missing filename. */ |
| 363 | return; |
| 364 | } |
| 365 | zFile = g.argv[i+1]; |
| 366 | read_args_lines(i,zFile); |
| 367 | } |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | /* |
| 372 | ** This procedure runs first. |
| 373 | */ |
| @@ -379,11 +301,11 @@ | |
| 379 | |
| 380 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 381 | g.now = time(0); |
| 382 | g.argc = argc; |
| 383 | g.argv = argv; |
| 384 | expand_args_arg(); |
| 385 | argc = g.argc; |
| 386 | argv = g.argv; |
| 387 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 388 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| 389 | zCmdName = "cgi"; |
| 390 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -232,142 +232,64 @@ | |
| 232 | } |
| 233 | return 1+(cnt>1); |
| 234 | } |
| 235 | |
| 236 | /* |
| 237 | ** Search g.argv for arguments "--args FILENAME". If found, then |
| 238 | ** (1) remove the two arguments from g.argv |
| 239 | ** (2) Read the file FILENAME |
| 240 | ** (3) Use the contents of FILE to replace the two removed arguments: |
| 241 | ** (a) Ignore blank lines in the file |
| 242 | ** (b) Each non-empty line of the file is an argument, except |
| 243 | ** (c) If the line begins with "-" and contains a space, it is broken |
| 244 | ** into two arguments at the space. |
| 245 | */ |
| 246 | static void expand_args_option(void){ |
| 247 | Blob file = empty_blob; /* Content of the file */ |
| 248 | Blob line = empty_blob; /* One line of the file */ |
| 249 | unsigned int nLine; /* Number of lines in the file*/ |
| 250 | unsigned int i, j, k; /* Loop counters */ |
| 251 | int n; /* Number of bytes in one line */ |
| 252 | char *z; /* General use string pointer */ |
| 253 | char **newArgv; /* New expanded g.argv under construction */ |
| 254 | |
| 255 | for(i=1; i<g.argc-1; i++){ |
| 256 | z = g.argv[i]; |
| 257 | if( z[0]!='-' ) continue; |
| 258 | z++; |
| 259 | if( z[0]=='-' ) z++; |
| 260 | if( z[0]==0 ) return; /* Stop searching at "--" */ |
| 261 | if( fossil_strcmp(z, "args")==0 ) break; |
| 262 | } |
| 263 | if( i>=g.argc-1 ) return; |
| 264 | |
| 265 | blob_read_from_file(&file, g.argv[i+1]); |
| 266 | z = blob_str(&file); |
| 267 | for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++; |
| 268 | newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) ); |
| 269 | for(j=0; j<i; j++) newArgv[j] = g.argv[j]; |
| 270 | |
| 271 | blob_rewind(&file); |
| 272 | while( (n = blob_line(&file, &line))>0 ){ |
| 273 | if( n<=1 ) continue; |
| 274 | z = blob_buffer(&line); |
| 275 | z[n-1] = 0; |
| 276 | newArgv[j++] = z; |
| 277 | if( z[0]=='-' ){ |
| 278 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 279 | if( z[k] ){ |
| 280 | z[k] = 0; |
| 281 | k++; |
| 282 | if( z[k] ) newArgv[j++] = &z[k]; |
| 283 | } |
| 284 | } |
| 285 | } |
| 286 | i += 2; |
| 287 | while( i<g.argc ) newArgv[j++] = g.argv[i++]; |
| 288 | newArgv[j] = 0; |
| 289 | g.argc = j; |
| 290 | g.argv = newArgv; |
| 291 | } |
| 292 | |
| 293 | /* |
| 294 | ** This procedure runs first. |
| 295 | */ |
| @@ -379,11 +301,11 @@ | |
| 301 | |
| 302 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 303 | g.now = time(0); |
| 304 | g.argc = argc; |
| 305 | g.argv = argv; |
| 306 | expand_args_option(); |
| 307 | argc = g.argc; |
| 308 | argv = g.argv; |
| 309 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 310 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| 311 | zCmdName = "cgi"; |
| 312 |