Fossil SCM
Initial --args FILENAME patch. Impl seems over-complex to me, but works as described in the list thread.
Commit
8a6568c3a32521cfacb6034e32f61ab3b141f883
Parent
312d522fe4cf3f0…
1 file changed
+137
+137
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -231,10 +231,144 @@ | ||
| 231 | 231 | return 0; |
| 232 | 232 | } |
| 233 | 233 | return 1+(cnt>1); |
| 234 | 234 | } |
| 235 | 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 | +} | |
| 236 | 370 | |
| 237 | 371 | /* |
| 238 | 372 | ** This procedure runs first. |
| 239 | 373 | */ |
| 240 | 374 | int main(int argc, char **argv){ |
| @@ -245,10 +379,13 @@ | ||
| 245 | 379 | |
| 246 | 380 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 247 | 381 | g.now = time(0); |
| 248 | 382 | g.argc = argc; |
| 249 | 383 | g.argv = argv; |
| 384 | + expand_args_arg(); | |
| 385 | + argc = g.argc; | |
| 386 | + argv = g.argv; | |
| 250 | 387 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 251 | 388 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| 252 | 389 | zCmdName = "cgi"; |
| 253 | 390 | }else if( argc<2 ){ |
| 254 | 391 | fossil_fatal("Usage: %s COMMAND ...\n" |
| 255 | 392 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -231,10 +231,144 @@ | |
| 231 | return 0; |
| 232 | } |
| 233 | return 1+(cnt>1); |
| 234 | } |
| 235 | |
| 236 | |
| 237 | /* |
| 238 | ** This procedure runs first. |
| 239 | */ |
| 240 | int main(int argc, char **argv){ |
| @@ -245,10 +379,13 @@ | |
| 245 | |
| 246 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 247 | g.now = time(0); |
| 248 | g.argc = argc; |
| 249 | g.argv = argv; |
| 250 | for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]); |
| 251 | if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){ |
| 252 | zCmdName = "cgi"; |
| 253 | }else if( argc<2 ){ |
| 254 | fossil_fatal("Usage: %s COMMAND ...\n" |
| 255 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -231,10 +231,144 @@ | |
| 231 | return 0; |
| 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 | */ |
| 374 | int main(int argc, char **argv){ |
| @@ -245,10 +379,13 @@ | |
| 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 | }else if( argc<2 ){ |
| 391 | fossil_fatal("Usage: %s COMMAND ...\n" |
| 392 |