have dprintf write to stderr and get flushed, instead of to stdout and
[dyninst.git] / dyninstAPI / tests / src / test4a.mutatee.c
1
2 /* Test application (Mutatee) */
3
4 /* $Id: test4a.mutatee.c,v 1.7 2004/01/19 21:54:17 schendel Exp $ */
5
6 #include <stdio.h>
7 #include <assert.h>
8 #include <sys/types.h>
9 #include <signal.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13
14 #if defined(i386_unknown_nt4_0) && !defined(__GNUC__)
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17 #include <process.h>
18 #define getpid _getpid
19 #else
20 #include <unistd.h>
21 #endif
22
23 #ifdef __cplusplus
24 int mutateeCplusplus = 1;
25 #else
26 int mutateeCplusplus = 0;
27 #endif
28
29 #ifndef COMPILER
30 #define COMPILER ""
31 #endif
32 const char *Builder_id=COMPILER; /* defined on compile line */
33
34 int debugPrint = 0;
35
36 /* control debug printf statements */
37 void dprintf(const char *fmt, ...) {
38    va_list args;
39    va_start(args, fmt);
40
41    if(debugPrint)
42       vfprintf(stderr, fmt, args);
43
44    va_end(args);
45
46    fflush(stderr);
47 }
48
49 #define TRUE    1
50 #define FALSE   0
51
52 int runAllTests = TRUE;
53 #define MAX_TEST 5
54 int runTest[MAX_TEST+1];
55
56 unsigned int globalVariable1_1 = 0xdeadbeef;
57 unsigned int globalVariable2_1 = 0xdeadbeef;
58
59 void func1_1()
60 {
61     globalVariable1_1 = 1000001;
62     exit((int) getpid());
63 }
64
65 /* should be called by parent */
66 void func2_3()
67 {
68     dprintf("pid %d in func2_3\n", (int) getpid());
69     globalVariable2_1 = 2000002;
70 }
71
72 /* should be called by child */
73 void func2_4()
74 {
75     dprintf("pid %d in func2_4\n", (int) getpid());
76     globalVariable2_1 = 2000003;
77 }
78
79 void func2_2() {
80     /* if we get this value at exit, no function was called */
81     globalVariable2_1 = 2000001;
82 }
83
84 void func2_1()
85 {
86 #ifndef i386_unknown_nt4_0
87     int pid;
88
89     pid = fork();
90     if (pid >= 0) {
91         /* both parent and child exit here */
92         func2_2();
93         dprintf("at exit of %d, globalVariable2_1 = %d\n", (int) getpid(),
94                 globalVariable2_1);
95         exit(getpid());
96     } else if (pid < 0) {
97         /* error case */
98         exit(pid);
99     }
100 #endif
101 }
102
103 unsigned int globalVariable3_1 = 0xdeadbeef;
104
105 void func3_1(int argc, char *argv[])
106 {
107     int i;
108     char *ch;
109     char **newArgv;
110
111     newArgv = (char **) calloc(sizeof(char *), argc +1);
112     for (i = 0; i < argc; i++) newArgv[i] = argv[i];
113
114     /* replace 4a in copy of myName by 4b */
115     newArgv[0] = strdup(argv[0]);
116     for (ch=newArgv[0]; *ch; ch++) {
117         if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
118     }
119
120     globalVariable3_1 = 3000001;
121     dprintf("Starting \"%s\"\n", newArgv[0]);
122     execvp(newArgv[0], newArgv);
123     perror("execvp");
124 }
125
126 unsigned int globalVariable4_1 = 0xdeadbeef;
127
128 void func4_3()
129 {
130     dprintf("in func4_3\n");
131     globalVariable4_1 = 4000002;
132 }
133
134 void func4_2()
135 {
136     dprintf("in func4_2\n");
137     /* call to func4_3 should be inserted here */
138 }
139
140 void func4_1(int argc, char *argv[])
141 {
142 #ifndef i386_unknown_nt4_0
143     int i;
144     int pid;
145     char *ch;
146     char **newArgv;
147
148     pid = fork();
149     if (pid == 0) {
150         newArgv = (char**) calloc(sizeof(char *), argc +1);
151         for (i = 0; i < argc; i++) newArgv[i] = argv[i];
152         
153         /* replace 4a in copy of myName by 4b */
154         newArgv[0] = strdup(argv[0]);
155         for (ch=newArgv[0]; *ch; ch++) {
156             if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
157         }
158         
159         globalVariable3_1 = 3000001;
160         dprintf("Starting \"%s\"\n", newArgv[0]);
161         execvp(newArgv[0], newArgv);
162         perror("execvp");
163     } else {
164         func4_2();
165 #if defined(rs6000_ibm_aix4_1)
166         /* On AIX the child dies when the parent exits, so wait */
167         sleep(3);
168 #endif
169         exit(getpid());
170     }
171 #endif
172 }
173
174 int main(int argc, char *argv[])
175 {                                       
176     int i, j;
177
178     for (i=1; i < argc; i++) {
179         if (!strcmp(argv[i], "-verbose")) {
180             debugPrint = TRUE;
181         } else if (!strcmp(argv[i], "-run")) {
182             runAllTests = FALSE;
183             for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
184             for (j=i+1; j < argc; j++) {
185                 unsigned int testId;
186                 if ((testId = atoi(argv[j]))) {
187                     if ((testId > 0) && (testId <= MAX_TEST)) {
188                         runTest[testId] = TRUE;
189                     } else {
190                         printf("invalid test %d requested\n", testId);
191                         exit(-1);
192                     }
193                 } else {
194                     /* end of test list */
195                     break;
196                 }
197             }
198             i=j-1;
199         } else {
200             fprintf(stderr, "Usage: %s [-verbose] -run <num> ..\n", argv[0]);
201             exit(-1);
202         }
203     }
204
205     if ((argc==1) || debugPrint)
206         printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
207                 mutateeCplusplus ? "C++" : "C", Builder_id);
208     if (argc==1) exit(0);
209
210     if (runTest[1]) func1_1();
211     if (runTest[2]) func2_1();
212     if (runTest[3]) func3_1(argc, argv);
213     if (runTest[4]) func4_1(argc, argv);
214
215     dprintf("Mutatee %s terminating.\n", argv[0]);
216     return 0;
217 }