1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
3f08c3bdfSopenharmony_ci * Copyright (c) 2012 Wanlong Gao <gaowanlong@cn.fujitsu.com>
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
6f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as
7f08c3bdfSopenharmony_ci * published by the Free Software Foundation.
8f08c3bdfSopenharmony_ci *
9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but
10f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12f08c3bdfSopenharmony_ci *
13f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along
14f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc.,
15f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci */
18f08c3bdfSopenharmony_ci/*
19f08c3bdfSopenharmony_ci *	 TEST1
20f08c3bdfSopenharmony_ci *	 -----
21f08c3bdfSopenharmony_ci *		Call clone() with all resources shared.
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci *		CHILD:
24f08c3bdfSopenharmony_ci *			modify the shared resources
25f08c3bdfSopenharmony_ci *			return 1 on success
26f08c3bdfSopenharmony_ci *		PARENT:
27f08c3bdfSopenharmony_ci *			wait for child to finish
28f08c3bdfSopenharmony_ci *			verify that the shared resourses are modified
29f08c3bdfSopenharmony_ci *			return 1 on success
30f08c3bdfSopenharmony_ci *		If parent & child returns successfully
31f08c3bdfSopenharmony_ci *			test passed
32f08c3bdfSopenharmony_ci *		else
33f08c3bdfSopenharmony_ci *			test failed
34f08c3bdfSopenharmony_ci *
35f08c3bdfSopenharmony_ci *	 TEST2
36f08c3bdfSopenharmony_ci *	 -----
37f08c3bdfSopenharmony_ci *		Call clone() with no resources shared.
38f08c3bdfSopenharmony_ci *
39f08c3bdfSopenharmony_ci *		CHILD:
40f08c3bdfSopenharmony_ci *			modify the resources in child's address space
41f08c3bdfSopenharmony_ci *			return 1 on success
42f08c3bdfSopenharmony_ci *		PARENT:
43f08c3bdfSopenharmony_ci *			wait for child to finish
44f08c3bdfSopenharmony_ci *			verify that the parent's resourses are not modified
45f08c3bdfSopenharmony_ci *			return 1 on success
46f08c3bdfSopenharmony_ci *		If parent & child returns successfully
47f08c3bdfSopenharmony_ci *			test passed
48f08c3bdfSopenharmony_ci *		else
49f08c3bdfSopenharmony_ci *			test failed
50f08c3bdfSopenharmony_ci */
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci#if defined UCLINUX && !__THROW
53f08c3bdfSopenharmony_ci/* workaround for libc bug */
54f08c3bdfSopenharmony_ci#define __THROW
55f08c3bdfSopenharmony_ci#endif
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci#define _GNU_SOURCE
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ci#include <errno.h>
60f08c3bdfSopenharmony_ci#include <fcntl.h>
61f08c3bdfSopenharmony_ci#include <sys/wait.h>
62f08c3bdfSopenharmony_ci#include <sys/types.h>
63f08c3bdfSopenharmony_ci#include <sys/syscall.h>
64f08c3bdfSopenharmony_ci#include <sched.h>
65f08c3bdfSopenharmony_ci#include "test.h"
66f08c3bdfSopenharmony_ci#include "safe_macros.h"
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci#define FLAG_ALL (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)
69f08c3bdfSopenharmony_ci#define FLAG_NONE SIGCHLD
70f08c3bdfSopenharmony_ci#define PARENT_VALUE 1
71f08c3bdfSopenharmony_ci#define CHILD_VALUE 2
72f08c3bdfSopenharmony_ci#define TRUE 1
73f08c3bdfSopenharmony_ci#define FALSE 0
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci#include "clone_platform.h"
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_cistatic void setup(void);
78f08c3bdfSopenharmony_cistatic int test_setup(void);
79f08c3bdfSopenharmony_cistatic void cleanup(void);
80f08c3bdfSopenharmony_cistatic void test_cleanup(void);
81f08c3bdfSopenharmony_cistatic int child_fn();
82f08c3bdfSopenharmony_cistatic int parent_test1(void);
83f08c3bdfSopenharmony_cistatic int parent_test2(void);
84f08c3bdfSopenharmony_cistatic int test_VM(void);
85f08c3bdfSopenharmony_cistatic int test_FS(void);
86f08c3bdfSopenharmony_cistatic int test_FILES(void);
87f08c3bdfSopenharmony_cistatic int test_SIG(void);
88f08c3bdfSopenharmony_cistatic int modified_VM(void);
89f08c3bdfSopenharmony_cistatic int modified_FS(void);
90f08c3bdfSopenharmony_cistatic int modified_FILES(void);
91f08c3bdfSopenharmony_cistatic int modified_SIG(void);
92f08c3bdfSopenharmony_cistatic void sig_child_defined_handler(int);
93f08c3bdfSopenharmony_cistatic void sig_default_handler();
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_cistatic int fd_parent;
96f08c3bdfSopenharmony_cistatic char file_name[25];
97f08c3bdfSopenharmony_cistatic int parent_variable;
98f08c3bdfSopenharmony_cistatic char cwd_parent[FILENAME_MAX];
99f08c3bdfSopenharmony_cistatic int parent_got_signal, child_pid;
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_cichar *TCID = "clone02";
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_cistruct test_case_t {
104f08c3bdfSopenharmony_ci	int flags;
105f08c3bdfSopenharmony_ci	int (*parent_fn) ();
106f08c3bdfSopenharmony_ci} test_cases[] = {
107f08c3bdfSopenharmony_ci	{
108f08c3bdfSopenharmony_ci	FLAG_ALL, parent_test1}, {
109f08c3bdfSopenharmony_ci	FLAG_NONE, parent_test2}
110f08c3bdfSopenharmony_ci};
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ciint TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ciint main(int ac, char **av)
115f08c3bdfSopenharmony_ci{
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	int lc;
118f08c3bdfSopenharmony_ci	void *child_stack;
119f08c3bdfSopenharmony_ci	int status, i;
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci	setup();
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci	child_stack = malloc(CHILD_STACK_SIZE);
126f08c3bdfSopenharmony_ci	if (child_stack == NULL)
127f08c3bdfSopenharmony_ci		tst_brkm(TBROK, cleanup, "Cannot allocate stack for child");
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
130f08c3bdfSopenharmony_ci		tst_count = 0;
131f08c3bdfSopenharmony_ci
132f08c3bdfSopenharmony_ci		for (i = 0; i < TST_TOTAL; ++i) {
133f08c3bdfSopenharmony_ci			if (test_setup() != 0) {
134f08c3bdfSopenharmony_ci				tst_resm(TWARN, "test_setup() failed, skipping this test case");
135f08c3bdfSopenharmony_ci				continue;
136f08c3bdfSopenharmony_ci			}
137f08c3bdfSopenharmony_ci
138f08c3bdfSopenharmony_ci			/* Test the system call */
139f08c3bdfSopenharmony_ci			TEST(ltp_clone(test_cases[i].flags, child_fn, NULL,
140f08c3bdfSopenharmony_ci				       CHILD_STACK_SIZE, child_stack));
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci			/* check return code */
143f08c3bdfSopenharmony_ci			if (TEST_RETURN == -1) {
144f08c3bdfSopenharmony_ci				tst_resm(TFAIL | TTERRNO, "clone() failed");
145f08c3bdfSopenharmony_ci				/* Cleanup & continue with next test case */
146f08c3bdfSopenharmony_ci				test_cleanup();
147f08c3bdfSopenharmony_ci				continue;
148f08c3bdfSopenharmony_ci			}
149f08c3bdfSopenharmony_ci
150f08c3bdfSopenharmony_ci			/* Wait for child to finish */
151f08c3bdfSopenharmony_ci			if ((wait(&status)) == -1) {
152f08c3bdfSopenharmony_ci				tst_resm(TWARN | TERRNO,
153f08c3bdfSopenharmony_ci					 "wait failed; skipping testcase");
154f08c3bdfSopenharmony_ci				/* Cleanup & continue with next test case */
155f08c3bdfSopenharmony_ci				test_cleanup();
156f08c3bdfSopenharmony_ci				continue;
157f08c3bdfSopenharmony_ci			}
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ci			if (WTERMSIG(status))
160f08c3bdfSopenharmony_ci				tst_resm(TWARN, "child exitied with signal %d",
161f08c3bdfSopenharmony_ci					 WTERMSIG(status));
162f08c3bdfSopenharmony_ci
163f08c3bdfSopenharmony_ci			/*
164f08c3bdfSopenharmony_ci			 * Check the return value from child function and
165f08c3bdfSopenharmony_ci			 * parent function. If both functions returned
166f08c3bdfSopenharmony_ci			 * successfully, test passed, else failed
167f08c3bdfSopenharmony_ci			 */
168f08c3bdfSopenharmony_ci			if (WIFEXITED(status) && WEXITSTATUS(status) == 0 &&
169f08c3bdfSopenharmony_ci			    test_cases[i].parent_fn())
170f08c3bdfSopenharmony_ci				tst_resm(TPASS, "Test Passed");
171f08c3bdfSopenharmony_ci			else
172f08c3bdfSopenharmony_ci				tst_resm(TFAIL, "Test Failed");
173f08c3bdfSopenharmony_ci
174f08c3bdfSopenharmony_ci			/* Do test specific cleanup */
175f08c3bdfSopenharmony_ci			test_cleanup();
176f08c3bdfSopenharmony_ci		}
177f08c3bdfSopenharmony_ci	}
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci	free(child_stack);
180f08c3bdfSopenharmony_ci
181f08c3bdfSopenharmony_ci	cleanup();
182f08c3bdfSopenharmony_ci	tst_exit();
183f08c3bdfSopenharmony_ci}
184f08c3bdfSopenharmony_ci
185f08c3bdfSopenharmony_cistatic void setup(void)
186f08c3bdfSopenharmony_ci{
187f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
188f08c3bdfSopenharmony_ci	TEST_PAUSE;
189f08c3bdfSopenharmony_ci	tst_tmpdir();
190f08c3bdfSopenharmony_ci
191f08c3bdfSopenharmony_ci	/* Get unique file name for each child process */
192f08c3bdfSopenharmony_ci	if ((sprintf(file_name, "parent_file_%ld", syscall(__NR_gettid))) <= 0)
193f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "sprintf() failed");
194f08c3bdfSopenharmony_ci}
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_cistatic void cleanup(void)
197f08c3bdfSopenharmony_ci{
198f08c3bdfSopenharmony_ci	if (unlink(file_name) == -1)
199f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "unlink(%s) failed", file_name);
200f08c3bdfSopenharmony_ci	tst_rmdir();
201f08c3bdfSopenharmony_ci}
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_cistatic int test_setup(void)
204f08c3bdfSopenharmony_ci{
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci	struct sigaction def_act;
207f08c3bdfSopenharmony_ci
208f08c3bdfSopenharmony_ci	/* Save current working directory of parent */
209f08c3bdfSopenharmony_ci	if (getcwd(cwd_parent, sizeof(cwd_parent)) == NULL) {
210f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "getcwd() failed in test_setup()");
211f08c3bdfSopenharmony_ci		return -1;
212f08c3bdfSopenharmony_ci	}
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci	/*
215f08c3bdfSopenharmony_ci	 * Set value for parent_variable in parent, which will be
216f08c3bdfSopenharmony_ci	 * changed by child in test_VM(), for testing CLONE_VM flag
217f08c3bdfSopenharmony_ci	 */
218f08c3bdfSopenharmony_ci	parent_variable = PARENT_VALUE;
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	/*
221f08c3bdfSopenharmony_ci	 * Open file from parent, which will be closed by
222f08c3bdfSopenharmony_ci	 * child in test_FILES(), used for testing CLONE_FILES flag
223f08c3bdfSopenharmony_ci	 */
224f08c3bdfSopenharmony_ci	fd_parent = open(file_name, O_CREAT | O_RDWR, 0777);
225f08c3bdfSopenharmony_ci	if (fd_parent == -1) {
226f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "open() failed in test_setup()");
227f08c3bdfSopenharmony_ci		return -1;
228f08c3bdfSopenharmony_ci	}
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_ci	/*
231f08c3bdfSopenharmony_ci	 * set parent_got_signal to FALSE, used for testing
232f08c3bdfSopenharmony_ci	 * CLONE_SIGHAND flag
233f08c3bdfSopenharmony_ci	 */
234f08c3bdfSopenharmony_ci	parent_got_signal = FALSE;
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci	/* Setup signal handler for SIGUSR2 */
237f08c3bdfSopenharmony_ci	def_act.sa_handler = sig_default_handler;
238f08c3bdfSopenharmony_ci	def_act.sa_flags = SA_RESTART;
239f08c3bdfSopenharmony_ci	sigemptyset(&def_act.sa_mask);
240f08c3bdfSopenharmony_ci
241f08c3bdfSopenharmony_ci	if (sigaction(SIGUSR2, &def_act, NULL) == -1) {
242f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "sigaction() failed in test_setup()");
243f08c3bdfSopenharmony_ci		return -1;
244f08c3bdfSopenharmony_ci	}
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	return 0;
247f08c3bdfSopenharmony_ci}
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_cistatic void test_cleanup(void)
250f08c3bdfSopenharmony_ci{
251f08c3bdfSopenharmony_ci
252f08c3bdfSopenharmony_ci	/* Restore parent's working directory */
253f08c3bdfSopenharmony_ci	SAFE_CHDIR(cleanup, cwd_parent);
254f08c3bdfSopenharmony_ci
255f08c3bdfSopenharmony_ci}
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_cistatic int child_fn(void)
258f08c3bdfSopenharmony_ci{
259f08c3bdfSopenharmony_ci
260f08c3bdfSopenharmony_ci	/* save child pid */
261f08c3bdfSopenharmony_ci	child_pid = syscall(__NR_gettid);
262f08c3bdfSopenharmony_ci
263f08c3bdfSopenharmony_ci	if (test_VM() == 0 && test_FILES() == 0 && test_FS() == 0 &&
264f08c3bdfSopenharmony_ci	    test_SIG() == 0)
265f08c3bdfSopenharmony_ci		_exit(0);
266f08c3bdfSopenharmony_ci	_exit(1);
267f08c3bdfSopenharmony_ci}
268f08c3bdfSopenharmony_ci
269f08c3bdfSopenharmony_cistatic int parent_test1(void)
270f08c3bdfSopenharmony_ci{
271f08c3bdfSopenharmony_ci
272f08c3bdfSopenharmony_ci	/*
273f08c3bdfSopenharmony_ci	 * For first test case (with all flags set), all resources are
274f08c3bdfSopenharmony_ci	 * shared between parent and child. So whatever changes made by
275f08c3bdfSopenharmony_ci	 * child should get reflected in parent also. modified_*()
276f08c3bdfSopenharmony_ci	 * functions check this. All of them should return 1 for
277f08c3bdfSopenharmony_ci	 * parent_test1() to return 1
278f08c3bdfSopenharmony_ci	 */
279f08c3bdfSopenharmony_ci
280f08c3bdfSopenharmony_ci	if (modified_VM() && modified_FILES() && modified_FS() &&
281f08c3bdfSopenharmony_ci	    modified_SIG())
282f08c3bdfSopenharmony_ci		return 0;
283f08c3bdfSopenharmony_ci	return -1;
284f08c3bdfSopenharmony_ci}
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_cistatic int parent_test2(void)
287f08c3bdfSopenharmony_ci{
288f08c3bdfSopenharmony_ci
289f08c3bdfSopenharmony_ci	/*
290f08c3bdfSopenharmony_ci	 * For second test case (with no resouce shared), all of the
291f08c3bdfSopenharmony_ci	 * modified_*() functions should return 0 for parent_test2()
292f08c3bdfSopenharmony_ci	 * to return 1
293f08c3bdfSopenharmony_ci	 */
294f08c3bdfSopenharmony_ci	if (modified_VM() || modified_FILES() || modified_FS() ||
295f08c3bdfSopenharmony_ci	    modified_SIG())
296f08c3bdfSopenharmony_ci		return 0;
297f08c3bdfSopenharmony_ci
298f08c3bdfSopenharmony_ci	return -1;
299f08c3bdfSopenharmony_ci}
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci/*
302f08c3bdfSopenharmony_ci * test_VM() - function to change parent_variable from child's
303f08c3bdfSopenharmony_ci *	       address space. If CLONE_VM flag is set, child shares
304f08c3bdfSopenharmony_ci *	       the memory space with parent so this will be visible
305f08c3bdfSopenharmony_ci *	       to parent also.
306f08c3bdfSopenharmony_ci */
307f08c3bdfSopenharmony_ci
308f08c3bdfSopenharmony_cistatic int test_VM(void)
309f08c3bdfSopenharmony_ci{
310f08c3bdfSopenharmony_ci	parent_variable = CHILD_VALUE;
311f08c3bdfSopenharmony_ci	return 0;
312f08c3bdfSopenharmony_ci}
313f08c3bdfSopenharmony_ci
314f08c3bdfSopenharmony_ci/*
315f08c3bdfSopenharmony_ci * test_FILES() - This function closes a file descriptor opened by
316f08c3bdfSopenharmony_ci *		  parent. If CLONE_FILES flag is set, the parent and
317f08c3bdfSopenharmony_ci *		  the child process share the same file descriptor
318f08c3bdfSopenharmony_ci *		  table. so this affects the parent also
319f08c3bdfSopenharmony_ci */
320f08c3bdfSopenharmony_cistatic int test_FILES(void)
321f08c3bdfSopenharmony_ci{
322f08c3bdfSopenharmony_ci	if (close(fd_parent) == -1) {
323f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "close failed in test_FILES");
324f08c3bdfSopenharmony_ci		return -1;
325f08c3bdfSopenharmony_ci	}
326f08c3bdfSopenharmony_ci	return 0;
327f08c3bdfSopenharmony_ci}
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ci/*
330f08c3bdfSopenharmony_ci * test_FS() -  This function changes the current working directory
331f08c3bdfSopenharmony_ci *		of the child process. If CLONE_FS flag is set, this
332f08c3bdfSopenharmony_ci *		will be visible to parent also.
333f08c3bdfSopenharmony_ci */
334f08c3bdfSopenharmony_cistatic int test_FS(void)
335f08c3bdfSopenharmony_ci{
336f08c3bdfSopenharmony_ci	char *test_tmpdir;
337f08c3bdfSopenharmony_ci	int rval;
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci	test_tmpdir = tst_get_tmpdir();
340f08c3bdfSopenharmony_ci	if (test_tmpdir == NULL) {
341f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "tst_get_tmpdir failed");
342f08c3bdfSopenharmony_ci		rval = -1;
343f08c3bdfSopenharmony_ci	} else if (chdir(test_tmpdir) == -1) {
344f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "chdir failed in test_FS");
345f08c3bdfSopenharmony_ci		rval = -1;
346f08c3bdfSopenharmony_ci	} else {
347f08c3bdfSopenharmony_ci		rval = 0;
348f08c3bdfSopenharmony_ci	}
349f08c3bdfSopenharmony_ci
350f08c3bdfSopenharmony_ci	free(test_tmpdir);
351f08c3bdfSopenharmony_ci	return rval;
352f08c3bdfSopenharmony_ci}
353f08c3bdfSopenharmony_ci
354f08c3bdfSopenharmony_ci/*
355f08c3bdfSopenharmony_ci * test_SIG() - This function changes the signal handler for SIGUSR2
356f08c3bdfSopenharmony_ci *		signal for child. If CLONE_SIGHAND flag is set, this
357f08c3bdfSopenharmony_ci *		affects parent also.
358f08c3bdfSopenharmony_ci */
359f08c3bdfSopenharmony_cistatic int test_SIG(void)
360f08c3bdfSopenharmony_ci{
361f08c3bdfSopenharmony_ci
362f08c3bdfSopenharmony_ci	struct sigaction new_act;
363f08c3bdfSopenharmony_ci
364f08c3bdfSopenharmony_ci	new_act.sa_handler = sig_child_defined_handler;
365f08c3bdfSopenharmony_ci	new_act.sa_flags = SA_RESTART;
366f08c3bdfSopenharmony_ci	sigemptyset(&new_act.sa_mask);
367f08c3bdfSopenharmony_ci
368f08c3bdfSopenharmony_ci	/* Set signal handler to sig_child_defined_handler */
369f08c3bdfSopenharmony_ci	if (sigaction(SIGUSR2, &new_act, NULL) == -1) {
370f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "signal failed in test_SIG");
371f08c3bdfSopenharmony_ci		return -1;
372f08c3bdfSopenharmony_ci	}
373f08c3bdfSopenharmony_ci
374f08c3bdfSopenharmony_ci	/* Send SIGUSR2 signal to parent */
375f08c3bdfSopenharmony_ci	if (kill(getppid(), SIGUSR2) == -1) {
376f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "kill failed in test_SIG");
377f08c3bdfSopenharmony_ci		return -1;
378f08c3bdfSopenharmony_ci	}
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_ci	return 0;
381f08c3bdfSopenharmony_ci}
382f08c3bdfSopenharmony_ci
383f08c3bdfSopenharmony_ci/*
384f08c3bdfSopenharmony_ci * modified_VM() - This function is called by parent process to check
385f08c3bdfSopenharmony_ci *		   whether child's modification to parent_variable
386f08c3bdfSopenharmony_ci *		   is visible to parent
387f08c3bdfSopenharmony_ci */
388f08c3bdfSopenharmony_ci
389f08c3bdfSopenharmony_cistatic int modified_VM(void)
390f08c3bdfSopenharmony_ci{
391f08c3bdfSopenharmony_ci
392f08c3bdfSopenharmony_ci	if (parent_variable == CHILD_VALUE)
393f08c3bdfSopenharmony_ci		/* child has modified parent_variable */
394f08c3bdfSopenharmony_ci		return 1;
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci	return 0;
397f08c3bdfSopenharmony_ci}
398f08c3bdfSopenharmony_ci
399f08c3bdfSopenharmony_ci/*
400f08c3bdfSopenharmony_ci * modified_FILES() - This function checks for file descriptor table
401f08c3bdfSopenharmony_ci *		      modifications done by child
402f08c3bdfSopenharmony_ci */
403f08c3bdfSopenharmony_cistatic int modified_FILES(void)
404f08c3bdfSopenharmony_ci{
405f08c3bdfSopenharmony_ci	char buff[20];
406f08c3bdfSopenharmony_ci
407f08c3bdfSopenharmony_ci	if (((read(fd_parent, buff, sizeof(buff))) == -1) && (errno == EBADF))
408f08c3bdfSopenharmony_ci		/* Child has closed this file descriptor */
409f08c3bdfSopenharmony_ci		return 1;
410f08c3bdfSopenharmony_ci
411f08c3bdfSopenharmony_ci	/* close fd_parent */
412f08c3bdfSopenharmony_ci	if ((close(fd_parent)) == -1)
413f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "close() failed in modified_FILES()");
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_ci	return 0;
416f08c3bdfSopenharmony_ci}
417f08c3bdfSopenharmony_ci
418f08c3bdfSopenharmony_ci/*
419f08c3bdfSopenharmony_ci * modified_FS() - This function checks parent's current working directory
420f08c3bdfSopenharmony_ci *		   to see whether its modified by child or not.
421f08c3bdfSopenharmony_ci */
422f08c3bdfSopenharmony_cistatic int modified_FS(void)
423f08c3bdfSopenharmony_ci{
424f08c3bdfSopenharmony_ci	char cwd[FILENAME_MAX];
425f08c3bdfSopenharmony_ci
426f08c3bdfSopenharmony_ci	if ((getcwd(cwd, sizeof(cwd))) == NULL)
427f08c3bdfSopenharmony_ci		tst_resm(TWARN | TERRNO, "getcwd() failed");
428f08c3bdfSopenharmony_ci
429f08c3bdfSopenharmony_ci	if (!(strcmp(cwd, cwd_parent)))
430f08c3bdfSopenharmony_ci		/* cwd hasn't changed */
431f08c3bdfSopenharmony_ci		return 0;
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci	return 1;
434f08c3bdfSopenharmony_ci}
435f08c3bdfSopenharmony_ci
436f08c3bdfSopenharmony_ci/*
437f08c3bdfSopenharmony_ci * modified_SIG() - This function checks whether child has changed
438f08c3bdfSopenharmony_ci *		    parent's signal handler for signal, SIGUSR2
439f08c3bdfSopenharmony_ci */
440f08c3bdfSopenharmony_cistatic int modified_SIG(void)
441f08c3bdfSopenharmony_ci{
442f08c3bdfSopenharmony_ci
443f08c3bdfSopenharmony_ci	if (parent_got_signal)
444f08c3bdfSopenharmony_ci		/*
445f08c3bdfSopenharmony_ci		 * parent came through sig_child_defined_handler()
446f08c3bdfSopenharmony_ci		 * this means child has changed parent's handler
447f08c3bdfSopenharmony_ci		 */
448f08c3bdfSopenharmony_ci		return 1;
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	return 0;
451f08c3bdfSopenharmony_ci}
452f08c3bdfSopenharmony_ci
453f08c3bdfSopenharmony_ci/*
454f08c3bdfSopenharmony_ci * sig_child_defined_handler()  - Signal handler installed by child
455f08c3bdfSopenharmony_ci */
456f08c3bdfSopenharmony_cistatic void sig_child_defined_handler(int pid)
457f08c3bdfSopenharmony_ci{
458f08c3bdfSopenharmony_ci	if ((syscall(__NR_gettid)) == child_pid)
459f08c3bdfSopenharmony_ci		/* Child got signal, give warning */
460f08c3bdfSopenharmony_ci		tst_resm(TWARN, "Child got SIGUSR2 signal");
461f08c3bdfSopenharmony_ci	else
462f08c3bdfSopenharmony_ci		parent_got_signal = TRUE;
463f08c3bdfSopenharmony_ci}
464f08c3bdfSopenharmony_ci
465f08c3bdfSopenharmony_ci/* sig_default_handler() - Default handler for parent */
466f08c3bdfSopenharmony_cistatic void sig_default_handler(void)
467f08c3bdfSopenharmony_ci{
468f08c3bdfSopenharmony_ci}
469