1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2001
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*
21 * NAME
22 * 	setsid01.c
23 *
24 * DESCRIPTION
25 * 	Test to check the error and trivial conditions in setsid system call
26 *
27 * USAGE
28 * 	setsid01
29 *
30 * RESTRICTIONS
31 * 	This test doesn't follow good LTP format - PLEASE FIX!
32 */
33#include <sys/wait.h>
34#include <limits.h>
35#include <signal.h>
36#include <errno.h>
37#include <unistd.h>
38#include <sys/param.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include "test.h"
42
43#define INVAL_FLAG	-1
44#define USER2		301
45#define INVAL_MAXGRP	NGROUPS_MAX + 1
46#define INVAL_USER	999999
47#define INVAL_PID	999999
48
49char *TCID = "setsid01";
50int TST_TOTAL = 1;
51
52#ifdef UCLINUX
53static char *argv0;
54#endif
55
56void do_child_1(void);
57void do_child_2(void);
58void setup(void);
59void cleanup(void);
60
61int main(int ac, char **av)
62{
63	int pid;
64	int fail = 0;
65	int ret, status;
66	int exno = 0;
67
68	int lc;
69
70	tst_parse_opts(ac, av, NULL, NULL);
71#ifdef UCLINUX
72	argv0 = av[0];
73
74	maybe_run_child(&do_child_1, "n", 1);
75	maybe_run_child(&do_child_2, "n", 2);
76#endif
77
78	/*
79	 * perform global setup for the test
80	 */
81	setup();
82
83	for (lc = 0; TEST_LOOPING(lc); lc++) {
84
85		/* reset tst_count in case we are looping */
86		tst_count = 0;
87
88		/*
89		 * When the process group having forked of a child
90		 * and then it attached itself to another process
91		 * group and tries to setsid
92		 */
93		pid = FORK_OR_VFORK();
94
95		if (pid == 0) {
96			if ((pid = FORK_OR_VFORK()) == -1) {
97				tst_resm(TFAIL, "Fork failed");
98
99			}
100			if (pid == 0) {
101#ifdef UCLINUX
102				if (self_exec(argv0, "n", 1) < 0) {
103					tst_resm(TFAIL, "self_exec failed");
104
105				}
106#else
107				do_child_1();
108#endif
109			} else {
110				if (setpgid(0, 0) < 0) {
111					tst_resm(TFAIL,
112						 "setpgid(parent) failed: %s",
113						 strerror(errno));
114					fail = 1;
115				}
116
117				if ((ret = wait(&status)) > 0) {
118					if (status != 0) {
119						tst_resm(TFAIL,
120							 "Test {%d} exited "
121							 "status 0x%0x (wanted 0x0)",
122							 ret, status);
123						fail = 1;
124					}
125				}
126			}
127			exit(0);
128		} else {
129			if ((ret = wait(&status)) > 0) {
130				if (status != 0) {
131					tst_resm(TFAIL, "Test {%d} exited "
132						 "status 0x%0x (wanted 0x0)",
133						 ret, status);
134					fail = 1;
135				}
136			}
137		}
138
139		if (!(fail || exno)) {
140			tst_resm(TPASS, "all misc tests passed");
141		}
142	}
143	cleanup();
144	tst_exit();
145
146}
147
148/*
149 * do_child_1()
150 */
151void do_child_1(void)
152{
153	int exno = 0;
154	int retval, ret, status;
155	int pid;
156
157	sleep(1);
158
159	if (setpgid(0, 0) < 0) {
160		tst_resm(TFAIL, "setpgid(0,0) failed: %s", strerror(errno));
161		exno = 1;
162	}
163
164	if ((pid = FORK_OR_VFORK()) == -1) {
165		tst_brkm(TFAIL, NULL, "Fork failed");
166	}
167	if (pid == 0) {
168#ifdef UCLINUX
169		if (self_exec(argv0, "n", 2) < 0) {
170			tst_brkm(TFAIL, NULL, "self_exec failed");
171		}
172#else
173		do_child_2();
174#endif
175	} else {
176		retval = setpgid(0, getppid());
177		if (retval < 0) {
178			tst_resm(TFAIL, "setpgid failed, errno :%d", errno);
179			exno = 2;
180		}
181
182		retval = setsid();
183
184		if (errno == EPERM) {
185			tst_resm(TPASS, "setsid SUCCESS to set "
186				 "errno to EPERM");
187		} else {
188			tst_resm(TFAIL, "setsid failed, expected %d, "
189				 "return %d", -1, errno);
190			exno = 3;
191		}
192		kill(pid, SIGKILL);
193		if ((ret = wait(&status)) > 0) {
194			if (status != 9) {
195				tst_resm(TFAIL,
196					 "Test {%d} exited status 0x%-x (wanted 0x9)",
197					 ret, status);
198				exno = 4;
199			}
200		}
201	}
202	exit(exno);
203}
204
205/*
206 * do_child_2()
207 */
208void do_child_2(void)
209{
210	for (;;) ;
211}
212
213/*
214 * setup() - performs all ONE TIME setup for this test
215 */
216void setup(void)
217{
218
219	tst_sig(FORK, DEF_HANDLER, cleanup);
220
221	umask(0);
222
223	TEST_PAUSE;
224}
225
226/*
227 * cleanup() - performs all the ONE TIME cleanup for this test at completion
228 * 	       or premature exit
229 */
230void cleanup(void)
231{
232
233}
234