source: tools/repeat.c @ 5eba8ce

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 5eba8ce was 5eba8ce, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Fixed bug in repeat program

  • Property mode set to 100644
File size: 3.0 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <signal.h>
4#include <stdbool.h>
5#include <string.h>
6
7#include <getopt.h>
8#include <unistd.h>
9
10#include <sys/types.h>
11#include <sys/wait.h>
12
13int repetitions = 0;
14bool stop_on_error = false;
15char * this_cmd = NULL;
16bool print_iterations = false;
17
18void parse_args(int argc, char * argv[]);
19void setup();
20int run();
21
22int main(int argc, char * argv[]) {
23        parse_args(argc, argv);
24        setup();
25        for(int i = 0; i < repetitions; i++) {
26                if(print_iterations) {
27                        printf("\r%d / %d", i, repetitions);
28                        fflush(stdout);
29                }
30                int retcode = run();
31                if( !WIFEXITED(retcode) ) {
32                        printf("FAILURE: %d @ %d\n", retcode, i + 1);
33                }
34                if( !WIFEXITED(retcode) && stop_on_error ) {
35                        return retcode;
36                }
37        }
38
39        if(print_iterations) {
40                printf("\r%d / %d\n", repetitions, repetitions);
41        }
42
43        return 0;
44}
45
46void usage( FILE * out, int code ) {
47        fprintf(out, "%s [OPTION] [--] N CMD\n", this_cmd);
48        fprintf(out, "Repeat CMD N times\n\n");
49        fprintf(out, "\t-h,--help\tprint this usage message\n");
50        fprintf(out, "\t-s\t\tstop on error\n");
51        fprintf(out, "\t-i\t\toutput iterations instead of CMD stdout\n");
52        fprintf(out, "\t-x\t\tprint CMD before running it\n");
53        exit(code);
54}
55
56char ** cmd_to_run = NULL;
57bool print_cmd = false;
58pid_t child_pid = 0;
59
60void error() {
61        fprintf(stderr,"\n");
62        usage(stderr, 1);
63}
64
65void parse_args(int argc, char * argv[]) {
66        this_cmd = argv[0];
67
68        enum { Help, };
69        static struct option long_opts[] = {
70                { "help", no_argument, 0, Help },
71                { 0, 0, 0, 0 }
72        }; // long_opts
73        int long_index;
74
75        int c;
76        while ( (c = getopt_long( argc, argv, "hsxi", long_opts, &long_index)) != -1 ) {
77                switch ( c ) {
78                        case Help:
79                        case 'h':
80                                usage(stdout, 0);
81                                break;
82                        case 's':
83                                stop_on_error = true;
84                                break;
85                        case 'x':
86                                print_cmd = true;
87                                break;
88                        case 'i':
89                                print_iterations = true;
90                                break;
91                        default:
92                                error("");
93                                break;
94                } // switch
95        } // while
96
97        if( argc < optind + 2 ) {
98                fprintf(stderr, "Too few arguments\n");
99                error();
100        }
101
102        char * pEnd;
103        char * repeats_c = argv[optind];
104        repetitions = strtol(repeats_c, &pEnd, 10);
105
106        bool is_number = (size_t)(pEnd - repeats_c) == strlen(repeats_c);
107        bool in_range  = repetitions > 0;
108        if( !is_number || !in_range ) {
109                fprintf(
110                        stderr,
111                        "repetitions option : %s not an number greater than 0\n",
112                        repeats_c
113                );
114                error();
115        }
116
117        cmd_to_run = argv + optind + 1;
118}
119
120void setup() {
121
122}
123
124int run() {
125        /* Duplicate this process. */
126        child_pid = fork();
127        if (child_pid != 0) {
128
129                /* This is the parent process. */
130                int status;
131                waitpid(child_pid, &status, 0);
132                child_pid = 0;
133                return status;
134        }
135        else {
136                /* Now execute PROGRAM, searching for it in the path.  */
137                if( print_cmd ) {
138                        char ** cmd = cmd_to_run;
139                        while (*cmd) {
140                                printf("%s ", *cmd);
141                                cmd++;
142                        }
143                        printf("\n");
144                }
145                if(print_iterations) {
146                        __attribute__((unused)) FILE * ignore =
147                                freopen("/dev/null", "w", stdout);
148                }
149                execvp ( *cmd_to_run, cmd_to_run);
150                /* The execvp  function returns only if an error occurs.  */
151                fprintf(stderr, "an error occurred in execvp\n");
152                abort ();
153        }
154
155        return 0;
156}
Note: See TracBrowser for help on using the repository browser.