diff --git a/README.md b/README.md index 88f7682..90bc63e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ TODO: - [ ] Make free-ing data consistent with null pointers. - [ ] Add documentation throughout (ownership, docstrings, etc.). -- [ ] Have main.c return status code of run.sh. - [ ] Organize variables in each function to the top? CLI utility for initializing projects in reproducible ways. diff --git a/include/error.h b/include/error.h index f5ce2ea..bf00fc2 100644 --- a/include/error.h +++ b/include/error.h @@ -22,6 +22,7 @@ enum ErrorCode { ERROR_VALIDATOR_FIELD_PROMPT_INVALID, ERROR_EVALUATOR_RUN_SH_NOT_FOUND, + ERROR_EVALUATOR_RUN_SH_NOT_EXEC, ERROR_EVALUATOR_RESPONSE_INVALID, }; diff --git a/include/evaluator.h b/include/evaluator.h index 809a93f..031d5e0 100644 --- a/include/evaluator.h +++ b/include/evaluator.h @@ -5,8 +5,10 @@ #include "error.h" #include "validator.h" -struct Error *evaluate_spec_json( - const struct Config *const config, const struct DynArray *const prompts +int evaluate_run_sh( + const struct Config *const config, + const struct DynArray *const prompts, + struct Error **error ); #endif /* _BOOTSTRAP_EVALUATOR_H */ diff --git a/main.c b/main.c index f7a7cfb..5f2cd34 100644 --- a/main.c +++ b/main.c @@ -38,13 +38,13 @@ static int run(const char *root_dir, const char *target) { goto cleanup_parsed; } - if ((error = evaluate_spec_json(config, prompts))) { - fprintf(stderr, "%s", error->message); + if ((retval = evaluate_run_sh(config, prompts, &error))) { + if (error) { + fprintf(stderr, "%s", error->message); + } goto cleanup_parsed; } - retval = EXIT_SUCCESS; - cleanup_prompts: if (prompts) { dyn_array_free(prompts); @@ -61,6 +61,7 @@ cleanup_config: cleanup_cwd: free(cwd); error_free(error); + return retval; } diff --git a/src/evaluator.c b/src/evaluator.c index 11dbbd5..fdcbee8 100644 --- a/src/evaluator.c +++ b/src/evaluator.c @@ -24,17 +24,25 @@ static struct Error *find_run_sh(const struct Config *const config) { ); } - // TODO: Check run.sh is executable. + if (!(sb.st_mode & S_IXUSR)) { + return ERROR_NEW( + ERROR_EVALUATOR_RUN_SH_NOT_EXEC, + config->target, + "/run.sh is not executable." + ); + } return 0; } -struct Error *evaluate_spec_json( - const struct Config *const config, const struct DynArray *const prompts +int evaluate_run_sh( + const struct Config *const config, + const struct DynArray *const prompts, + struct Error **error ) { - struct Error *error = find_run_sh(config); - if (error) { - return error; + *error = find_run_sh(config); + if (*error) { + return EXIT_FAILURE; } if (prompts) { @@ -61,8 +69,7 @@ struct Error *evaluate_spec_json( free(filepath); - // TODO: Want to return this status out. - int status = system(command); - - return 0; + int exit_code = system(command); + free((void *)command); + return WEXITSTATUS(exit_code); }