1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it
5f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as
6f08c3bdfSopenharmony_ci * published by the Free Software Foundation.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but
9f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it is
13f08c3bdfSopenharmony_ci * free of the rightful claim of any third person regarding infringement
14f08c3bdfSopenharmony_ci * or the like.  Any license provided herein, whether implied or
15f08c3bdfSopenharmony_ci * otherwise, applies only to this software file.  Patent licenses, if
16f08c3bdfSopenharmony_ci * any, provided herein do not apply to combinations of this program with
17f08c3bdfSopenharmony_ci * other software, or any other product whatsoever.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along
20f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc.,
21f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24f08c3bdfSopenharmony_ci * Mountain View, CA  94043, or:
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * http://www.sgi.com
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci * For further information regarding this notice, see:
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci *
33f08c3bdfSopenharmony_ci *    OS Test - Silicon Graphics, Inc.
34f08c3bdfSopenharmony_ci *    TEST IDENTIFIER	: fork04
35f08c3bdfSopenharmony_ci *    TEST TITLE	: Child inheritance of Environment Variables after fork()
36f08c3bdfSopenharmony_ci *    PARENT DOCUMENT	: frktds01
37f08c3bdfSopenharmony_ci *    TEST CASE TOTAL	: 3
38f08c3bdfSopenharmony_ci *    WALL CLOCK TIME	: 1
39f08c3bdfSopenharmony_ci *    CPU TYPES		: ALL
40f08c3bdfSopenharmony_ci *    AUTHOR		: Kathy Olmsted
41f08c3bdfSopenharmony_ci *    CO-PILOT		: Steve Shaw
42f08c3bdfSopenharmony_ci *    DATE STARTED	: 06/17/92
43f08c3bdfSopenharmony_ci *    INITIAL RELEASE	: UNICOS 7.0
44f08c3bdfSopenharmony_ci *
45f08c3bdfSopenharmony_ci *    TEST CASES
46f08c3bdfSopenharmony_ci *       Test these environment variables correctly inherited by child:
47f08c3bdfSopenharmony_ci *       1. TERM
48f08c3bdfSopenharmony_ci *       2. NoTSetzWq
49f08c3bdfSopenharmony_ci *       3. TESTPROG
50f08c3bdfSopenharmony_ci *
51f08c3bdfSopenharmony_ci *    INPUT SPECIFICATIONS
52f08c3bdfSopenharmony_ci * 	The standard options for system call tests are accepted.
53f08c3bdfSopenharmony_ci *	(See the parse_opts(3) man page).
54f08c3bdfSopenharmony_ci *
55f08c3bdfSopenharmony_ci *    DURATION
56f08c3bdfSopenharmony_ci * 	Terminates - with frequency and infinite modes.
57f08c3bdfSopenharmony_ci *
58f08c3bdfSopenharmony_ci *    SIGNALS
59f08c3bdfSopenharmony_ci * 	Uses SIGUSR1 to pause before test if option set.
60f08c3bdfSopenharmony_ci * 	(See the parse_opts(3) man page).
61f08c3bdfSopenharmony_ci *
62f08c3bdfSopenharmony_ci *    ENVIRONMENTAL NEEDS
63f08c3bdfSopenharmony_ci *      No run-time environmental needs.
64f08c3bdfSopenharmony_ci *
65f08c3bdfSopenharmony_ci *    DETAILED DESCRIPTION
66f08c3bdfSopenharmony_ci *
67f08c3bdfSopenharmony_ci * 	Setup:
68f08c3bdfSopenharmony_ci * 	  Setup signal handling.
69f08c3bdfSopenharmony_ci *        Make and change to a temporary directory.
70f08c3bdfSopenharmony_ci *	  Pause for SIGUSR1 if option specified.
71f08c3bdfSopenharmony_ci *        Add TESTPROG variable to the environment
72f08c3bdfSopenharmony_ci *
73f08c3bdfSopenharmony_ci * 	Test:
74f08c3bdfSopenharmony_ci *	 Loop if the proper options are given.
75f08c3bdfSopenharmony_ci *	 fork()
76f08c3bdfSopenharmony_ci *	 Check return code, if system call failed (return=-1)
77f08c3bdfSopenharmony_ci *		Log the errno
78f08c3bdfSopenharmony_ci *	   CHILD:
79f08c3bdfSopenharmony_ci *              open a temp file
80f08c3bdfSopenharmony_ci *		Determine environment values and write to file
81f08c3bdfSopenharmony_ci *		close file containing test values.
82f08c3bdfSopenharmony_ci *		exit.
83f08c3bdfSopenharmony_ci *	    PARENT:
84f08c3bdfSopenharmony_ci *		Wait for child to exit.
85f08c3bdfSopenharmony_ci *              Verify exit status
86f08c3bdfSopenharmony_ci *		Open file containing test values.
87f08c3bdfSopenharmony_ci *		For each test case:
88f08c3bdfSopenharmony_ci *			Read the value from the file.
89f08c3bdfSopenharmony_ci *			Determine and report PASS/FAIL result.
90f08c3bdfSopenharmony_ci *
91f08c3bdfSopenharmony_ci * 	Cleanup:
92f08c3bdfSopenharmony_ci * 	  Print errno log and/or timing stats if options given
93f08c3bdfSopenharmony_ci *        Remove the temporary directory and exit.
94f08c3bdfSopenharmony_ci */
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci#include <stdlib.h>
97f08c3bdfSopenharmony_ci#include <sys/types.h>
98f08c3bdfSopenharmony_ci#include <sys/wait.h>
99f08c3bdfSopenharmony_ci#include <unistd.h>
100f08c3bdfSopenharmony_ci#include <fcntl.h>
101f08c3bdfSopenharmony_ci#include <string.h>
102f08c3bdfSopenharmony_ci#include <sys/param.h>
103f08c3bdfSopenharmony_ci#include <signal.h>
104f08c3bdfSopenharmony_ci#include <errno.h>
105f08c3bdfSopenharmony_ci#include "test.h"
106f08c3bdfSopenharmony_ci#include "safe_macros.h"
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_cichar *TCID = "fork04";
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci#define	KIDEXIT	42
111f08c3bdfSopenharmony_ci#define MAX_LINE_LENGTH 256
112f08c3bdfSopenharmony_ci#define OUTPUT_FILE  "env.out"
113f08c3bdfSopenharmony_ci#define ENV_NOT_SET  "getenv() does not find variable set"
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci/* list of environment variables to test */
116f08c3bdfSopenharmony_cichar *environ_list[] = { "TERM", "NoTSetzWq", "TESTPROG" };
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci#define NUMBER_OF_ENVIRON (sizeof(environ_list)/sizeof(char *))
119f08c3bdfSopenharmony_ciint TST_TOTAL = NUMBER_OF_ENVIRON;
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_cistatic void cleanup(void)
122f08c3bdfSopenharmony_ci{
123f08c3bdfSopenharmony_ci	tst_rmdir();
124f08c3bdfSopenharmony_ci}
125f08c3bdfSopenharmony_ci
126f08c3bdfSopenharmony_cistatic void setup(void)
127f08c3bdfSopenharmony_ci{
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ci	tst_sig(FORK, DEF_HANDLER, cleanup);
130f08c3bdfSopenharmony_ci	TEST_PAUSE;
131f08c3bdfSopenharmony_ci	tst_tmpdir();
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci	/* add a variable to the environment */
134f08c3bdfSopenharmony_ci	putenv("TESTPROG=FRKTCS04");
135f08c3bdfSopenharmony_ci}
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_cistatic void child_environment(void)
138f08c3bdfSopenharmony_ci{
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci	int fildes;
141f08c3bdfSopenharmony_ci	int index;
142f08c3bdfSopenharmony_ci	char msg[MAX_LINE_LENGTH];
143f08c3bdfSopenharmony_ci	char *var;
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_ci	fildes = creat(OUTPUT_FILE, 0700);
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ci	for (index = 0; index < (int)NUMBER_OF_ENVIRON; index++) {
148f08c3bdfSopenharmony_ci		memset(msg, 0, MAX_LINE_LENGTH);
149f08c3bdfSopenharmony_ci
150f08c3bdfSopenharmony_ci		var = getenv(environ_list[index]);
151f08c3bdfSopenharmony_ci		if (var == NULL)
152f08c3bdfSopenharmony_ci			(void)sprintf(msg, "%s:%s", environ_list[index],
153f08c3bdfSopenharmony_ci				      ENV_NOT_SET);
154f08c3bdfSopenharmony_ci		else
155f08c3bdfSopenharmony_ci			(void)sprintf(msg, "%s:%s", environ_list[index], var);
156f08c3bdfSopenharmony_ci		/* includes extra null chars */
157f08c3bdfSopenharmony_ci		write(fildes, msg, sizeof(msg));
158f08c3bdfSopenharmony_ci	}
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_ci	close(fildes);
161f08c3bdfSopenharmony_ci}
162f08c3bdfSopenharmony_ci
163f08c3bdfSopenharmony_ci/*
164f08c3bdfSopenharmony_ci * Compare parent env string to child's string.
165f08c3bdfSopenharmony_ci * Each string is in the format:  <env var>:<value>
166f08c3bdfSopenharmony_ci */
167f08c3bdfSopenharmony_cistatic int cmp_env_strings(char *pstring, char *cstring)
168f08c3bdfSopenharmony_ci{
169f08c3bdfSopenharmony_ci	char *penv, *cenv, *pvalue, *cvalue;
170f08c3bdfSopenharmony_ci
171f08c3bdfSopenharmony_ci	/*
172f08c3bdfSopenharmony_ci	 * Break pstring into env and value
173f08c3bdfSopenharmony_ci	 */
174f08c3bdfSopenharmony_ci	penv = pstring;
175f08c3bdfSopenharmony_ci	pvalue = strchr(pstring, ':');
176f08c3bdfSopenharmony_ci	if (pvalue == NULL) {
177f08c3bdfSopenharmony_ci		tst_resm(TBROK,
178f08c3bdfSopenharmony_ci			 "internal error - parent's env string not in correct format:'%s'",
179f08c3bdfSopenharmony_ci			 pstring);
180f08c3bdfSopenharmony_ci		return -1;
181f08c3bdfSopenharmony_ci	} else {
182f08c3bdfSopenharmony_ci		*pvalue = '\0';
183f08c3bdfSopenharmony_ci		pvalue++;
184f08c3bdfSopenharmony_ci		if (*pvalue == '\0') {
185f08c3bdfSopenharmony_ci			tst_resm(TBROK,
186f08c3bdfSopenharmony_ci				 "internal error - missing parent's env value");
187f08c3bdfSopenharmony_ci			return -1;
188f08c3bdfSopenharmony_ci		}
189f08c3bdfSopenharmony_ci	}
190f08c3bdfSopenharmony_ci
191f08c3bdfSopenharmony_ci	/*
192f08c3bdfSopenharmony_ci	 * Break cstring into env and value
193f08c3bdfSopenharmony_ci	 */
194f08c3bdfSopenharmony_ci	cenv = cstring;
195f08c3bdfSopenharmony_ci	cvalue = strchr(cstring, ':');
196f08c3bdfSopenharmony_ci	if (cvalue == NULL) {
197f08c3bdfSopenharmony_ci		tst_resm(TBROK,
198f08c3bdfSopenharmony_ci			 "internal error - parent's env string not in correct format:'%s'",
199f08c3bdfSopenharmony_ci			 cstring);
200f08c3bdfSopenharmony_ci		return -1;
201f08c3bdfSopenharmony_ci	} else {
202f08c3bdfSopenharmony_ci		*cvalue = '\0';
203f08c3bdfSopenharmony_ci		cvalue++;
204f08c3bdfSopenharmony_ci		if (*cvalue == '\0') {
205f08c3bdfSopenharmony_ci			tst_resm(TBROK,
206f08c3bdfSopenharmony_ci				 "internal error - missing child's env value");
207f08c3bdfSopenharmony_ci			return -1;
208f08c3bdfSopenharmony_ci		}
209f08c3bdfSopenharmony_ci	}
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	if (strcmp(penv, cenv) != 0) {
212f08c3bdfSopenharmony_ci		tst_resm(TBROK, "internal error - parent(%s) != child (%s) env",
213f08c3bdfSopenharmony_ci			 penv, cenv);
214f08c3bdfSopenharmony_ci		return -1;
215f08c3bdfSopenharmony_ci	}
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci	if (strcmp(pvalue, cvalue) != 0) {
218f08c3bdfSopenharmony_ci		tst_resm(TFAIL,
219f08c3bdfSopenharmony_ci			 "Env var %s changed after fork(), parent's %s, child's %s",
220f08c3bdfSopenharmony_ci			 penv, pvalue, cvalue);
221f08c3bdfSopenharmony_ci	} else {
222f08c3bdfSopenharmony_ci		tst_resm(TPASS, "Env var %s unchanged after fork(): %s",
223f08c3bdfSopenharmony_ci			 penv, cvalue);
224f08c3bdfSopenharmony_ci	}
225f08c3bdfSopenharmony_ci	return 0;
226f08c3bdfSopenharmony_ci
227f08c3bdfSopenharmony_ci}
228f08c3bdfSopenharmony_ci
229f08c3bdfSopenharmony_ci/***************************************************************
230f08c3bdfSopenharmony_ci * parent_environment - the parent side of the environment tests
231f08c3bdfSopenharmony_ci *        determine values for the variables
232f08c3bdfSopenharmony_ci *        read the values determined by the child
233f08c3bdfSopenharmony_ci *        compare values
234f08c3bdfSopenharmony_ci ***************************************************************/
235f08c3bdfSopenharmony_civoid parent_environment(void)
236f08c3bdfSopenharmony_ci{
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci	int fildes;
239f08c3bdfSopenharmony_ci	char tmp_line[MAX_LINE_LENGTH];
240f08c3bdfSopenharmony_ci	char parent_value[MAX_LINE_LENGTH];
241f08c3bdfSopenharmony_ci	unsigned int index;
242f08c3bdfSopenharmony_ci	int ret;
243f08c3bdfSopenharmony_ci	char *var;
244f08c3bdfSopenharmony_ci
245f08c3bdfSopenharmony_ci	fildes = SAFE_OPEN(cleanup, OUTPUT_FILE, O_RDWR);
246f08c3bdfSopenharmony_ci	for (index = 0; index < NUMBER_OF_ENVIRON; index++) {
247f08c3bdfSopenharmony_ci		ret = read(fildes, tmp_line, MAX_LINE_LENGTH);
248f08c3bdfSopenharmony_ci		if (ret == 0) {
249f08c3bdfSopenharmony_ci			tst_resm(TBROK,
250f08c3bdfSopenharmony_ci				 "fork() test. parent_environment: failed to read from file with %d (%s)",
251f08c3bdfSopenharmony_ci				 errno, strerror(errno));
252f08c3bdfSopenharmony_ci		} else {
253f08c3bdfSopenharmony_ci
254f08c3bdfSopenharmony_ci			var = getenv(environ_list[index]);
255f08c3bdfSopenharmony_ci			if (var == NULL)
256f08c3bdfSopenharmony_ci				sprintf(parent_value, "%s:%s",
257f08c3bdfSopenharmony_ci					environ_list[index], ENV_NOT_SET);
258f08c3bdfSopenharmony_ci			else
259f08c3bdfSopenharmony_ci				sprintf(parent_value, "%s:%s",
260f08c3bdfSopenharmony_ci					environ_list[index], var);
261f08c3bdfSopenharmony_ci
262f08c3bdfSopenharmony_ci			cmp_env_strings(parent_value, tmp_line);
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci		}
265f08c3bdfSopenharmony_ci	}
266f08c3bdfSopenharmony_ci
267f08c3bdfSopenharmony_ci	close(fildes);
268f08c3bdfSopenharmony_ci}
269f08c3bdfSopenharmony_ci
270f08c3bdfSopenharmony_ciint main(int ac, char **av)
271f08c3bdfSopenharmony_ci{
272f08c3bdfSopenharmony_ci	int lc;
273f08c3bdfSopenharmony_ci	int kid_status;
274f08c3bdfSopenharmony_ci	int wait_status;
275f08c3bdfSopenharmony_ci	int fails;
276f08c3bdfSopenharmony_ci
277f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	setup();
280f08c3bdfSopenharmony_ci
281f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
282f08c3bdfSopenharmony_ci		tst_count = 0;
283f08c3bdfSopenharmony_ci		fails = 0;
284f08c3bdfSopenharmony_ci
285f08c3bdfSopenharmony_ci		TEST(fork());
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci		if (TEST_RETURN == -1) {
288f08c3bdfSopenharmony_ci			/* fork failed */
289f08c3bdfSopenharmony_ci			tst_brkm(TFAIL, cleanup,
290f08c3bdfSopenharmony_ci				 "fork() failed with %d (%s)",
291f08c3bdfSopenharmony_ci				 TEST_ERRNO, strerror(TEST_ERRNO));
292f08c3bdfSopenharmony_ci		} else if (TEST_RETURN == 0) {
293f08c3bdfSopenharmony_ci			/* child */
294f08c3bdfSopenharmony_ci			/* determine environment variables */
295f08c3bdfSopenharmony_ci			child_environment();
296f08c3bdfSopenharmony_ci			/* exit with known value */
297f08c3bdfSopenharmony_ci			exit(KIDEXIT);
298f08c3bdfSopenharmony_ci		} else {
299f08c3bdfSopenharmony_ci			/* parent of successful fork */
300f08c3bdfSopenharmony_ci			/* wait for the child to complete */
301f08c3bdfSopenharmony_ci			wait_status = waitpid(TEST_RETURN, &kid_status, 0);
302f08c3bdfSopenharmony_ci			/* validate the child exit status */
303f08c3bdfSopenharmony_ci			if (wait_status == TEST_RETURN) {
304f08c3bdfSopenharmony_ci				if (kid_status != KIDEXIT << 8) {
305f08c3bdfSopenharmony_ci					tst_brkm(TBROK, cleanup,
306f08c3bdfSopenharmony_ci						 "fork(): Incorrect child status returned on wait(): %d",
307f08c3bdfSopenharmony_ci						 kid_status);
308f08c3bdfSopenharmony_ci					fails++;
309f08c3bdfSopenharmony_ci				}
310f08c3bdfSopenharmony_ci			} else {
311f08c3bdfSopenharmony_ci				tst_brkm(TBROK, cleanup,
312f08c3bdfSopenharmony_ci					 "fork(): wait() for child status failed with %d errno: %d : %s",
313f08c3bdfSopenharmony_ci					 wait_status, errno,
314f08c3bdfSopenharmony_ci					 strerror(errno));
315f08c3bdfSopenharmony_ci				fails++;
316f08c3bdfSopenharmony_ci			}
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci			if (fails == 0) {
319f08c3bdfSopenharmony_ci				/* verification tests */
320f08c3bdfSopenharmony_ci				parent_environment();
321f08c3bdfSopenharmony_ci			}
322f08c3bdfSopenharmony_ci		}
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci	}
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci	cleanup();
327f08c3bdfSopenharmony_ci	tst_exit();
328f08c3bdfSopenharmony_ci}
329