Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / tests / src / test4a.mutatee.c
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /* Test application (Mutatee) */
33
34 /* $Id: test4a.mutatee.c,v 1.14 2006/04/21 00:30:21 mjbrim Exp $ */
35
36 #include <stdio.h>
37 #include <assert.h>
38 #include <sys/types.h>
39 #include <signal.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stdarg.h>
43 #include <errno.h>
44
45 #if defined(i386_unknown_nt4_0) && !defined(__GNUC__)
46 #define WIN32_LEAN_AND_MEAN
47 #include <windows.h>
48 #include <process.h>
49 #define getpid _getpid
50 #else
51 #include <unistd.h>
52 #endif
53
54 #ifdef __cplusplus
55 int mutateeCplusplus = 1;
56 #else
57 int mutateeCplusplus = 0;
58 #endif
59
60 #ifndef COMPILER
61 #define COMPILER ""
62 #endif
63 const char *Builder_id=COMPILER; /* defined on compile line */
64
65 int debugPrint = 0;
66
67 /* control debug printf statements */
68 void dprintf(const char *fmt, ...) {
69    va_list args;
70    va_start(args, fmt);
71
72    if(debugPrint)
73       vfprintf(stderr, fmt, args);
74
75    va_end(args);
76
77    fflush(stderr);
78 }
79
80 #define TRUE    1
81 #define FALSE   0
82
83 int runAllTests = TRUE;
84 #define MAX_TEST 5
85 int runTest[MAX_TEST+1];
86
87 unsigned int globalVariable1_1 = 0xdeadbeef;
88 unsigned int globalVariable2_1 = 0xdeadbeef;
89
90 void func1_1()
91 {
92     globalVariable1_1 = 1000001;
93     exit((int) getpid());
94 }
95
96 /* should be called by parent */
97 void func2_3()
98 {
99     dprintf("pid %d in func2_3\n", (int) getpid());
100     globalVariable2_1 = 2000002;
101 }
102
103 /* should be called by child */
104 void func2_4()
105 {
106     dprintf("pid %d in func2_4\n", (int) getpid());
107     globalVariable2_1 = 2000003;
108 }
109
110 void func2_2() {
111     /* if we get this value at exit, no function was called */
112     globalVariable2_1 = 2000001;
113 }
114
115 void func2_1()
116 {
117 #ifndef i386_unknown_nt4_0
118     int pid;
119
120     pid = fork();
121     dprintf("fork result: %d\n", pid);
122     if (pid >= 0) {
123         /* both parent and child exit here */
124         func2_2();
125         dprintf("at exit of %d, globalVariable2_1 = %d\n", (int) getpid(),
126                 globalVariable2_1);
127
128 #if defined(rs6000_ibm_aix4_1)
129         if( pid == 0){
130                 /* On AIX the child dies when the parent exits, so wait */
131                 /* apparently the parent needs to wake up occasionally to keep Dyninst happy */
132                 dprintf("%d SLEEPING\n",getpid());
133                 sleep(5);
134                 dprintf("%d SLEEP MORE\n",getpid());
135                 sleep(1);
136                 dprintf("%d SLEEP MORE\n",getpid());
137                 sleep(5);
138                 dprintf("%d DONE SLEEPING\n",getpid());
139         }
140 #endif
141         
142         /* Make the parent exit first (again, testing) */
143         if (pid == 0) {
144                 dprintf("%d SLEEPING\n",getpid());
145             sleep(1);
146                 dprintf("%d SLEEPING\n",getpid());
147             sleep(1);
148                 dprintf("%d SLEEPING\n",getpid());
149             sleep(1);
150                 dprintf("%d SLEEPING\n",getpid());
151             sleep(1);
152                 dprintf("%d SLEEPING\n",getpid());
153             sleep(1);
154         }
155
156         dprintf("Mutatee %d exiting...\n", getpid());
157         exit(getpid());
158     } else if (pid < 0) {
159         /* error case */
160         exit(pid);
161     }
162 #endif
163 }
164
165 unsigned int globalVariable3_1 = 0xdeadbeef;
166
167 void func3_1(int argc, char *argv[])
168 {
169     int i;
170     char *ch;
171     char **newArgv;
172     char *testb;
173
174     newArgv = (char **) calloc(sizeof(char *), argc +1);
175     for (i = 0; i < argc; i++) newArgv[i] = argv[i];
176
177     /* prepend './' if necessary and replace 4a in copy of myName by 4b */
178     if(strncmp(argv[0], "./", 2)) {
179        testb = (char*) malloc(strlen(argv[0])+5);
180        assert(testb);
181        testb[0] = '.';
182        testb[1] = '/';
183        strcpy(&testb[2], argv[0]);
184        newArgv[0] = testb;
185     }
186     else
187        newArgv[0] = strdup(argv[0]);
188
189     for (ch=newArgv[0]; *ch; ch++) {
190         if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
191     }
192
193     globalVariable3_1 = 3000001;
194     dprintf("Starting \"%s\"\n", newArgv[0]);
195     errno = 0;
196     dprintf("Going into exec...\n");
197     execvp(newArgv[0], newArgv);
198     perror("execvp");
199     fprintf(stderr, "ERROR: Failed to exec \"%s\"\n", newArgv[0]);
200     exit(1);
201 }
202
203 unsigned int globalVariable4_1 = 0xdeadbeef;
204
205 void func4_3()
206 {
207     dprintf("in func4_3\n");
208     globalVariable4_1 = 4000002;
209 }
210
211 void func4_2()
212 {
213     dprintf("in func4_2\n");
214     /* call to func4_3 should be inserted here */
215 }
216
217 void func4_1(int argc, char *argv[])
218 {
219 #ifndef i386_unknown_nt4_0
220     int i;
221     int pid;
222     char *ch;
223     char **newArgv;
224     char *testb;
225
226     pid = fork();
227     if (pid == 0) {
228         newArgv = (char**) calloc(sizeof(char *), argc +1);
229         for (i = 0; i < argc; i++) newArgv[i] = argv[i];
230         
231         /* prepend './' if necessary and replace 4a in copy of myName by 4b */
232         if (strncmp(argv[0], "./", 2)) {
233            testb = (char*) malloc(strlen(argv[0])+5);
234            assert(testb);
235            testb[0] = '.';
236            testb[1] = '/';
237            strcpy(&testb[2], argv[0]);
238            newArgv[0] = testb;
239         }
240         else
241            newArgv[0] = strdup(argv[0]);
242
243         for (ch=newArgv[0]; *ch; ch++) {
244            if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
245         }
246         
247         globalVariable3_1 = 3000001;
248         dprintf("Starting \"%s\"\n", newArgv[0]);
249         execvp(newArgv[0], newArgv);
250         perror("execvp");
251         fprintf(stderr, "ERROR: Failed to exec \"%s\"\n", newArgv[0]);
252         exit(1);
253     } else {
254         func4_2();
255 #if defined(rs6000_ibm_aix4_1)
256         /* On AIX the child dies when the parent exits, so wait */
257         /* and the parent needs to wake up occasionally to keep dyninst happy*/
258         dprintf("%d SLEEPING\n",getpid());
259         sleep(10);
260         dprintf("%d SLEEP MORE\n",getpid());
261         sleep(2);
262         dprintf("%d SLEEP MORE\n",getpid());
263         sleep(5);
264         dprintf("%d DONE SLEEPING\n",getpid());
265
266 #endif
267         exit(getpid());
268     }
269 #endif
270 }
271
272 int main(int argc, char *argv[])
273 {                                       
274     int i, j;
275
276     for (i=1; i < argc; i++) {
277         if (!strcmp(argv[i], "-verbose")) {
278             debugPrint = TRUE;
279         } else if (!strcmp(argv[i], "-run")) {
280             runAllTests = FALSE;
281             for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
282             for (j=i+1; j < argc; j++) {
283                 unsigned int testId;
284                 if ((testId = atoi(argv[j]))) {
285                     if ((testId > 0) && (testId <= MAX_TEST)) {
286                         runTest[testId] = TRUE;
287                     } else {
288                         printf("invalid test %d requested\n", testId);
289                         exit(-1);
290                     }
291                 } else {
292                     /* end of test list */
293                     break;
294                 }
295             }
296             i=j-1;
297         } else {
298             fprintf(stderr, "Usage: %s [-verbose] -run <num> ..\n", argv[0]);
299             exit(-1);
300         }
301     }
302
303     if ((argc==1) || debugPrint)
304         printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
305                 mutateeCplusplus ? "C++" : "C", Builder_id);
306     if (argc==1) exit(0);
307
308     if (runTest[1]) func1_1();
309     if (runTest[2]) func2_1();
310     if (runTest[3]) func3_1(argc, argv);
311     if (runTest[4]) func4_1(argc, argv);
312
313     dprintf("Mutatee %s terminating.\n", argv[0]);
314     return 0;
315 }