source: tools/repeat.c@ 76e2113

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 76e2113 was 967e3c9, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Repeat tool can now redirect output

  • Property mode set to 100644
File size: 3.7 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 fprintf(out, "\t-a FILE\t\tredirect output of command to append to FILE\n");
54 fprintf(out, "\t-r FILE\t\tredirect output of command to FILE\n");
55 exit(code);
56}
57
58char ** cmd_to_run = NULL;
59bool print_cmd = false;
60bool redirect = false;
61bool redirect_append = false;
62char * redirect_to = "/dev/null";
63pid_t child_pid = 0;
64
65void error() {
66 fprintf(stderr,"\n");
67 usage(stderr, 1);
68}
69
70void parse_args(int argc, char * argv[]) {
71 this_cmd = argv[0];
72
73 enum { Help, };
74 static struct option long_opts[] = {
75 { "help", no_argument, 0, Help },
76 { 0, 0, 0, 0 }
77 }; // long_opts
78 int long_index;
79
80 int c;
81 while ( (c = getopt_long( argc, argv, "ahirsx", long_opts, &long_index)) != -1 ) {
82 switch ( c ) {
83 case Help:
84 case 'h':
85 usage(stdout, 0);
86 break;
87 case 's':
88 stop_on_error = true;
89 break;
90 case 'x':
91 print_cmd = true;
92 break;
93 case 'i':
94 print_iterations = true;
95 break;
96 case 'a':
97 if(redirect) { fprintf(stderr, "Cannot have -a and -r\n"); error(); }
98 redirect_append = true;
99 redirect_to = argv[optind];
100 optind++;
101 break;
102 case 'r':
103 if(redirect_append) { fprintf(stderr, "Cannot have -a and -r\n"); error(); }
104 redirect = true;
105 redirect_to = argv[optind];
106 optind++;
107 break;
108 default:
109 error("");
110 break;
111 } // switch
112 } // while
113
114 if( argc < optind + 2 ) {
115 fprintf(stderr, "Too few arguments\n");
116 error();
117 }
118
119 char * pEnd;
120 char * repeats_c = argv[optind];
121 repetitions = strtol(repeats_c, &pEnd, 10);
122
123 bool is_number = (size_t)(pEnd - repeats_c) == strlen(repeats_c);
124 bool in_range = repetitions > 0;
125 if( !is_number || !in_range ) {
126 fprintf(
127 stderr,
128 "repetitions option : %s not an number greater than 0\n",
129 repeats_c
130 );
131 error();
132 }
133
134 cmd_to_run = argv + optind + 1;
135}
136
137void setup() {
138
139}
140
141int run() {
142 /* Duplicate this process. */
143 child_pid = fork();
144 if (child_pid != 0) {
145
146 /* This is the parent process. */
147 int status;
148 waitpid(child_pid, &status, 0);
149 child_pid = 0;
150 return status;
151 }
152 else {
153 /* Now execute PROGRAM, searching for it in the path. */
154 if( print_cmd ) {
155 char ** cmd = cmd_to_run;
156 while (*cmd) {
157 printf("%s ", *cmd);
158 cmd++;
159 }
160 printf("\n");
161 }
162 if(print_iterations || redirect || redirect_append) {
163 __attribute__((unused)) FILE * ignore =
164 freopen(redirect_to, redirect_append ? "a" : "w" , stdout);
165 }
166 execvp ( *cmd_to_run, cmd_to_run);
167 /* The execvp function returns only if an error occurs. */
168 fprintf(stderr, "an error occurred in execvp\n");
169 abort ();
170 }
171
172 return 0;
173}
Note: See TracBrowser for help on using the repository browser.