#include #include #include #include #include #include #include #include #include int repetitions = 0; bool stop_on_error = false; char * this_cmd = NULL; bool print_iterations = false; void parse_args(int argc, char * argv[]); void setup(); int run(); int main(int argc, char * argv[]) { parse_args(argc, argv); setup(); for(int i = 0; i < repetitions; i++) { if(print_iterations) { printf("\r%d / %d", i, repetitions); } int retcode = run(); if( !WIFEXITED(retcode) ) { printf("FAILURE: %d @ %d\n", retcode, i + 1); } if( !WIFEXITED(retcode) && stop_on_error ) { return retcode; } } if(print_iterations) { printf("\r%d / %d\n", repetitions, repetitions); } return 0; } void usage( FILE * out, int code ) { fprintf(out, "%s [OPTION] [--] N CMD\n", this_cmd); fprintf(out, "Repeat CMD N times\n\n"); fprintf(out, "\t-h,--help\tprint this usage message\n"); fprintf(out, "\t-s\tstop on error\n"); fprintf(out, "\t-i\toutput iterations instead of CMD stdout\n"); fprintf(out, "\t-x\tprint CMD before running it\n"); exit(code); } char ** cmd_to_run = NULL; bool print_cmd = false; pid_t child_pid = 0; void error() { fprintf(stderr,"\n"); usage(stderr, 1); } void parse_args(int argc, char * argv[]) { this_cmd = argv[0]; enum { Help, }; static struct option long_opts[] = { { "help", no_argument, 0, Help }, { 0, 0, 0, 0 } }; // long_opts int long_index; int c; while ( (c = getopt_long( argc, argv, "hsxi", long_opts, &long_index)) != -1 ) { switch ( c ) { case Help: case 'h': usage(stdout, 0); break; case 's': stop_on_error = true; break; case 'x': print_cmd = true; break; case 'i': print_iterations = true; break; default: error(""); break; } // switch } // while if( argc < optind + 2 ) { fprintf(stderr, "Too few arguments\n"); error(); } char * pEnd; char * repeats_c = argv[optind]; repetitions = strtol(repeats_c, &pEnd, 10); bool is_number = (size_t)(pEnd - repeats_c) == strlen(repeats_c); bool in_range = repetitions > 0; if( !is_number || !in_range ) { fprintf( stderr, "repetitions option : %s not an number greater than 0\n", repeats_c ); error(); } cmd_to_run = argv + optind + 1; } void setup() { } int run() { /* Duplicate this process. */ child_pid = fork(); if (child_pid != 0) { /* This is the parent process. */ int status; waitpid(child_pid, &status, 0); child_pid = 0; return status; } else { /* Now execute PROGRAM, searching for it in the path. */ if( print_cmd ) { char ** cmd = cmd_to_run; while (*cmd) { printf("%s ", *cmd); cmd++; } printf("\n"); } if(print_iterations) { __attribute__((unused)) FILE * ignore = freopen("/dev/null", "w", stdout); } execvp ( *cmd_to_run, cmd_to_run); /* The execvp function returns only if an error occurs. */ fprintf(stderr, "an error occurred in execvp\n"); abort (); } return 0; }